测试结束之前验证rspec模拟

时间:2019-06-27 14:31:27

标签: ruby unit-testing rspec rspec-mocks

似乎在测试用例中使用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

3 个答案:

答案 0 :(得分:1)

您正在寻找rspec spies

  

间谍是支持此功能的替代测试类型   模式,方法是使用have_received让您期望事后收到消息。

您用fooallow(...).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