如何制作rspec-mocks'期待收到。急切地失败

时间:2016-03-23 10:54:46

标签: ruby rspec rspec-mocks

rspec-mocks'如果使用与传递给expect(target).to receive(:message).with(arg_matcher)的arg匹配器不匹配的参数调用目标,with将仅在测试结束时显示错误。有没有办法迫使它急切地失败 - 也就是说,一旦用不匹配的参数调用目标? RR以这种方式工作。

我面临的问题是,当我使用如上所述的arg_matcher设置此模拟时,测试开始失败,因为使用不同的参数调用目标,但是在测试结束之前另一个断言失败,所以我只从这个断言中看到错误,而不是从丢失的mock中看出错误(这会向我显示预期的params与实际调用的params之间的区别)。

使用rspec-mocks 3.3.2。

2 个答案:

答案 0 :(得分:2)

我不知道如何让receive急切地失败。但是,have_received急切地失败了,所以如果它是几个期望中的第一个,它将是未通过测试并且RSpec报告的那个。

class Foo
  def self.bar(baz)
  end
end

describe "RSpec" do
  it "reports a non-mock expectation failure before a mock expectation failure" do
    expect(Foo).to receive(:bar).with(1)
    expect(true).to be_falsy # RSpec reports this failure
    Foo.bar 2
  end

  it "reports a spy expectation failure when you'd expect it to be reported" do
    allow(Foo).to receive(:bar) # Spy on Foo
    Foo.bar 2
    expect(Foo).to have_received(:bar).with(1) # RSpec reports this failure
    expect(true).to be_falsy
  end

end

有关详细信息,请参阅the documentation of RSpec spies

如果

,这个解决方案可能是最好的
  • 如果您喜欢逻辑arrange-act-assert序列中的测试,就像我一样
  • 如果间谍期望失败,你不关心其他期望
  • 如果您介意设置间谍的allow的额外输入比aggregate_failures阻止
  • 更少。

常规模拟和Adarsh的解决方案更好

  • 你想看到两种期望的结果,无论是否失败
  • 如果您认为aggregate_failures阻止比设想间谍的allow的额外输入更少。

答案 1 :(得分:1)

  

测试开始失败,因为目标是用不同的参数调用的,但是在测试结束之前另一个断言失败了,所以我只看到来自这个断言的错误,而不是来自丢失的模拟

如果我正确读取这个,你在一个规范中有多个expect断言而第一个断言失败,所以你没有看到第二个/第三个断言失败?

如果是这样,我会考虑使用RSpec's aggregate_failures introduced in v3.3,它会收集失败但会运行后续断言:

aggregate_failures("verifying response") do
  expect(response.status).to eq(200)
  expect(response.headers).to include("Content-Type" => "text/plain")
  expect(response.body).to include("Success")
end

# Which gives you nice errors for all assertions

1) Client returns a successful response
     Got 3 failures:

     1.1) Got 3 failures from failure aggregation block "testing response".
          # ./spec/use_block_form_spec.rb:18
          # ./spec/use_block_form_spec.rb:10

          1.1.1) Failure/Error: expect(response.status).to eq(200)

                   expected: 200
                        got: 404

                   (compared using ==)
                 # ./spec/use_block_form_spec.rb:19

          1.1.2) Failure/Error: expect(response.headers).to include("Content-Type" => "application/json")
                   expected {"Content-Type" => "text/plain"} to include {"Content-Type" => "application/json"}
                   Diff:
                   @@ -1,2 +1,2 @@
                   -[{"Content-Type"=>"application/json"}]
                   +"Content-Type" => "text/plain",
                 # ./spec/use_block_form_spec.rb:20

          1.1.3) Failure/Error: expect(response.body).to eq('{"message":"Success"}')

                   expected: "{\"message\":\"Success\"}"
                        got: "Not Found"

                   (compared using ==)
                 # ./spec/use_block_form_spec.rb:21

     1.2) Failure/Error: expect(false).to be(true), "after hook failure"
            after hook failure
          # ./spec/use_block_form_spec.rb:6
          # ./spec/use_block_form_spec.rb:10

     1.3) Failure/Error: expect(false).to be(true), "around hook failure"
            around hook failure
          # ./spec/use_block_form_spec.rb:12

您还可以将描述块标记为aggregate_failures

RSpec.describe ClassName, :aggregate_failures do
  # stuff
end