Прежде всего: тесты должны проверять результаты вызванных методов, а не способ их реализации. Полагаясь на это, вы попадете в беду.
Но для этого могут быть веские причины, но подумайте, можете ли вы проверить это другим способом:
Допустим, что String#select
использует Array#select
для внутреннего использования, а последнееглючит при некоторых обстоятельствах. Лучше сделать тест, настроив юниверс таким образом, чтобы он вызывал ошибку и проверял, что поведение ошибки отсутствует. Затем исправьте String#select
и проверьте зеленый цвет. Это намного лучший подход, потому что тест теперь говорит всем , почему вы не должны использовать Array#select
для внутреннего использования. И если ошибка устранена, под солнцем проще всего удалить патч и проверить, что спецификация все еще зеленая.
При этом, если вам все еще нужно, вы можете использовать expect_any_instance_of
, чтобы подтвердить это, например, эта спецификация потерпит неудачу:
class String
def select(&block)
split.select(&block) # remove this to make the spec pass
end
end
specify do
expect_any_instance_of(Array).not_to receive(:select)
'foo'.select
end
Если вы не хотите использовать expect_any_instance_of
( по причинам ), вы можете временно перезаписать метод в классе для сбоя:
class String
def select(&block)
#split.select(&block)
end
end
before do
class Array
alias :backup_select :select
def select(*)
raise 'No'
end
end
end
after do
class Array
alias :select :backup_select # bring the original implementation back
end
end
specify do
expect { 'foo'.select }.not_to raise_error
end
Псевдоним необходим для возврата к исходной реализации, так что вы не путаетесьдо спецификации, которая запускается после этой.
Но вы можете видеть, насколько сложен и запутан этот подход.
В любом случае - то, что вы пытаетесь достичь, - это , наиболее вероятно, проблема дизайна, но трудно сказать без подробностей.