Похоже, что стандартный способ использования макетов rspec в тестовом примере — это сделать что-то вроде этого:
class MyTest
def setup
super
::RSpec::Mocks.setup(self)
end
def teardown
super
begin
::RSpec::Mocks.verify
ensure
::RSpec::Mocks.teardown
end
end
test "something"
foo = MyFoo.new
expect(foo).to receive(:bar).and_return(42)
ret = SomeClass.call_bar(foo)
assert_equal(42, ret)
end
end
Работает хорошо. Но если SomeClass.call_bar
использовала возврат foo.bar
в качестве возврата, и что-то было не так с кодом, так что foo.bar
никогда не вызывался, то я получаю отказ только из-за строки assert_equal(42, ret)
. Я не вижу никакой ошибки, например:
RSpec::Mocks::MockExpectationError: (foo).bar
expected: 1 time
received: 0 times
Если я удалю строку assert_equal(42, ret)
, то получу ошибку ожидания rspec. Но я хочу проверить обе вещи, что foo.bar
был вызван и окончательный возврат был 42. Более важно знать, что foo.bar
не вызывался, так как это источник причины, по которой 42 не было возвращено .
Если я ожидаю что-то вроде: expect(foo).not_to receive(:bar)
, то я получаю эту ошибку ожидания прямо в источнике вызова, а не позже во время разборки.
Теперь я могу сделать что-то вроде ::RSpec::Mocks.verify
непосредственно перед вызовом assert_equal
, но это кажется неправильным. Я также не уверен, должен ли я убирать макеты в этот момент или нет.
Есть ли какой-то синтаксис, например:
test "something"
foo = MyFoo.new
ret = nil
expect(foo).to receive(:bar).and_return(42).during do
ret = SomeClass.call_bar(foo)
end
assert_equal(42, ret)
end
Чтобы проверка происходила сразу после того, как блок перешел на during
? Или, может быть, если у вас есть несколько двойников, вы можете сделать что-то вроде:
expect(dbl1).to receive(:one)
expect(dbl2).to receive(:two)
expect(dbl3).to receive(:three)
verify(dbl1, dbl2, dbl3).during do
my_code
end