似乎在测试用例中使用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
,那么由于{{1 }}行。我看不到任何错误,例如:
assert_equal(42, ret)
如果我删除RSpec::Mocks::MockExpectationError: (foo).bar
expected: 1 time
received: 0 times
行,那么我确实会得到rspec预期错误。但是我想验证一下两者,assert_equal(42, ret)
被称为,而的最终返回值为42。更重要的是要知道未调用foo.bar
,因为这是没有返回42的原因。
如果我期望的是类似foo.bar
的东西,那么我确实会在呼叫的源头得到期望错误,而不是在拆卸期间。
现在,我可以像在调用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
答案 0 :(得分:1)
您正在寻找rspec spies。
间谍是支持此功能的替代测试类型 模式,方法是使用
have_received
让您期望事后收到消息。
您用foo
在allow(...).to receive
中创建了一个部分双倍,然后可以断言消息的接收:
test "something"
foo = MyFoo.new
allow(foo).to receive(:bar).and_return(42)
ret = SomeClass.call_bar(foo)
expect(foo).to have_received(:bar)
assert_equal(42, ret)
end
答案 1 :(得分:1)
我相信您需要的是汇总故障 https://relishapp.com/rspec/rspec-expectations/v/3-8/docs/aggregating-failures
在“正常”设置中,任何错误都会中止测试,并且不会检查以后的断言。
答案 2 :(得分:-2)
我不认为有任何内置方法,但是如果您添加以下类:
class VerifyDuring
def initialize(test, objects)
@test = test
@objects = objects
end
def during
yield
ensure
begin
@objects.each do |object|
RSpec::Mocks.proxy_for(object).verify
end
rescue Exception => e
@test.flunk e
end
end
end
以及测试类的以下方法:
def verify(*objects)
VerifyDuring.new(self, objects)
end
您可以这样做:
verify(dbl1, dbl2, dbl3).during do
my_code
end