Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 测试结束前验证rspec模拟_Ruby_Unit Testing_Rspec_Rspec Mocks - Fatal编程技术网

Ruby 测试结束前验证rspec模拟

Ruby 测试结束前验证rspec模拟,ruby,unit-testing,rspec,rspec-mocks,Ruby,Unit Testing,Rspec,Rspec Mocks,在测试用例中使用rspec模拟的标准方法似乎是这样做: classmytest def设置 超级的 ::RSpec::Mocks.setup(self) 结束 def拆卸 超级的 开始 ::RSpec::Mocks.verify 确保 ::RSpec::Mocks.teardown 结束 结束 测试“某物” foo=MyFoo.new 期望(foo).接收(:bar.)和返回(42) ret=SomeClass.call\u bar(foo) 断言相等(42,ret) 结束 结束 好的。但是如

在测试用例中使用rspec模拟的标准方法似乎是这样做:

classmytest
def设置
超级的
::RSpec::Mocks.setup(self)
结束
def拆卸
超级的
开始
::RSpec::Mocks.verify
确保
::RSpec::Mocks.teardown
结束
结束
测试“某物”
foo=MyFoo.new
期望(foo).接收(:bar.)和返回(42)
ret=SomeClass.call\u bar(foo)
断言相等(42,ret)
结束
结束
好的。但是如果
SomeClass.call\u bar
使用
foo.bar
的返回作为返回,并且代码出现了一些错误,以至于从未调用过
foo.bar
,那么我只会收到由于
assert\u 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)
,那么我确实会在调用的源代码处得到期望错误,而不是稍后在拆卸过程中

现在,我可以做一些类似于put
::RSpec::Mocks的事情。在调用
assert_equal
之前验证
,但这感觉不对。我也不确定我是否应该在这一点上清理模拟

是否有如下语法:

测试“某物”
foo=MyFoo.new
ret=零
预期(foo).在do期间接收(:bar.)和返回(42)
ret=SomeClass.call\u bar(foo)
结束
断言相等(42,ret)
结束
因此,在
期间,验证会在块传递到
之后立即进行?或者,如果你有多个替身,你可以这样做:

expect(dbl1).接收(:一)
期望(dbl2).接收(:2)
期望(dbl3).接收(:三)
验证(dbl1、dbl2、dbl3)
我的密码
结束

我不认为有任何内置方法可以做到这一点,但如果您添加以下类:

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(*对象)
VerifyDuring.new(自我、对象)
结束
您可以这样做:

验证(dbl1、dbl2、dbl3)
我的密码
结束
您正在寻找的

间谍是支持这一点的另一种双重测试类型 通过使用
have\u received
,您可以期望在事件发生后收到消息

您可以使用
allow(…)从
foo
中创建一个部分double。若要接收
,则可以断言消息的接收:

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

我相信你需要的是把失败汇总起来


在“正常”设置中,任何错误都会中止测试,并且不会检查以后的断言

这不会有帮助,因为失败的断言
expect(foo)。要接收(:bar)
将中止测试。我不同意这一点;OP指出知道调用没有发生是更重要的断言。我编写的测试,如果没有调用该方法,将导致指示该对象没有收到消息。如果返回的值取决于是否收到消息,则未收到消息始终意味着第二次测试失败。在这种情况下,聚合失败并不能帮助调试失败的原因,而且可能会弄乱局面。哦,对不起。我没有注意到断言顺序的变化。你能编辑一下你的回答吗,这样我就可以删除否决票了?这非常接近,
allow
之前的通话,然后
expect
之后的通话。。。我会给它一些时间看看是否有其他答案,但这是最接近的答案,可能会被接受。这并没有回答有关如何实际验证消息调用的问题。它仍在拆卸阶段进行验证,这是一个有助于在第一次失败的断言上中止测试的解决方案。这与我所需要的是一致的,但是
assert
来自minitest,而
expect
来自rspec,所以我认为它们不会聚合在一起。您尝试过吗?聚合意味着测试在第一次失败后不会中止,所以有可能会发生拆卸。我不需要这成为minitest的一个功能吗?我需要minitest在
assert_equal(42,ret)
失败后继续运行拆卸。它必须在报告中包含拆卸的故障/错误。