在测试结束前验证 rspec 个模拟
Verifying rspec mocks before the test is over
似乎在测试用例中使用 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
的 return 作为 return,并且代码有问题以至于 foo.bar
从未被调用,那么我只会收到由于 assert_equal(42, ret)
行而失败。我没有看到任何错误,例如:
RSpec::Mocks::MockExpectationError: (foo).bar
expected: 1 time
received: 0 times
如果我删除 assert_equal(42, ret)
行,那么我会得到 rspec 期望错误。但我想验证这两件事,即 foo.bar
被称为 和 最后的 return 是 42。更重要的是要知道 foo.bar
不是t 调用是因为这就是 42 未被 returned 的原因。
如果我期待这样的事情:expect(foo).not_to receive(:bar)
,那么我确实在调用的源头得到了期望错误,而不是在拆解的后期。
现在,我可以在调用 assert_equal
之前执行类似放置 ::RSpec::Mocks.verify
的操作,但这感觉不对。我也不确定此时是否应该清理模拟。
有没有像这样的语法:
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
我认为没有任何 built-in 方法可以做到这一点,但是如果您添加以下内容 class:
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
还有下面的方法给你测试class:
def verify(*objects)
VerifyDuring.new(self, objects)
end
你可以这样做:
verify(dbl1, dbl2, dbl3).during do
my_code
end
您正在寻找 rspec spies。
Spies are an alternate type of test double that support this
pattern by allowing you to expect that a message has been received after the fact, using have_received
.
您使用 allow(...).to receive
从 foo
中创建了一个部分双倍,然后可以声明消息的接收:
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
我相信你需要的是聚合失败
https://relishapp.com/rspec/rspec-expectations/v/3-8/docs/aggregating-failures
在 "normal" 设置中,任何错误都会中止测试并且不会检查后面的断言。
似乎在测试用例中使用 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
的 return 作为 return,并且代码有问题以至于 foo.bar
从未被调用,那么我只会收到由于 assert_equal(42, ret)
行而失败。我没有看到任何错误,例如:
RSpec::Mocks::MockExpectationError: (foo).bar
expected: 1 time
received: 0 times
如果我删除 assert_equal(42, ret)
行,那么我会得到 rspec 期望错误。但我想验证这两件事,即 foo.bar
被称为 和 最后的 return 是 42。更重要的是要知道 foo.bar
不是t 调用是因为这就是 42 未被 returned 的原因。
如果我期待这样的事情:expect(foo).not_to receive(:bar)
,那么我确实在调用的源头得到了期望错误,而不是在拆解的后期。
现在,我可以在调用 assert_equal
之前执行类似放置 ::RSpec::Mocks.verify
的操作,但这感觉不对。我也不确定此时是否应该清理模拟。
有没有像这样的语法:
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
我认为没有任何 built-in 方法可以做到这一点,但是如果您添加以下内容 class:
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
还有下面的方法给你测试class:
def verify(*objects)
VerifyDuring.new(self, objects)
end
你可以这样做:
verify(dbl1, dbl2, dbl3).during do
my_code
end
您正在寻找 rspec spies。
Spies are an alternate type of test double that support this pattern by allowing you to expect that a message has been received after the fact, using
have_received
.
您使用 allow(...).to receive
从 foo
中创建了一个部分双倍,然后可以声明消息的接收:
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
我相信你需要的是聚合失败 https://relishapp.com/rspec/rspec-expectations/v/3-8/docs/aggregating-failures
在 "normal" 设置中,任何错误都会中止测试并且不会检查后面的断言。