Rspec误报,因为在被测试的代码中挽救了失败异常

时间:2011-09-15 16:34:05

标签: ruby-on-rails-3 exception rspec rescue false-positive

我有一个我期望失败的rspec测试,但它正在通过,因为它正在测试的代码拯救了rspec引发的异常。以下是这种情况的一个例子:

class Thing do

  def self.method_being_tested( object )
    # ... do some stuff

    begin
      object.save!
    rescue Exception => e
      # Swallow the exception and log it
    end
  end

end

在rspec文件中:

describe "method_being_tested" do
  it "should not call 'save!' on the object passed in" do
    # ... set up the test conditions

    mock_object.should_not_receive( :save! )
    Thing.method_being_tested( mock_object )
  end
end

我知道执行是在达到“object.save!”被测试的方法的线,因此测试应该失败,但测试通过。使用救援块中的调试器,我发现以下内容:

(rdb:1) p e # print the exception object "e"
#<RSpec::Mocks::MockExpectationError: (Mock "TestObject_1001").save!
    expected: 0 times
    received: 1 time>

所以基本上测试失败了,但是失败正在被它试图测试的代码所抑制。我无法找到一种可行的方法来阻止此代码吞噬Rspec异常而不会以某种方式破坏代码。我不希望代码显式检查异常是否是Rspec异常,因为这是糟糕的设计(应该为代码编写测试,不应该为测试编写代码)。但我也无法检查异常是否是我想要捕获的任何特定类型,因为我希望它能够捕获可以在正常生产环境中引发的任何类型。

有人必须在我面前遇到这个问题!请帮我找到解决方案。

3 个答案:

答案 0 :(得分:4)

假设代码原样正确:

describe "method_being_tested" do
  it "should not call 'save!' on the object passed in" do
    # ... set up the test conditions
    calls = 0
    mock_object.stub(:save!) { calls += 1 }
    expect {Thing.method_being_tested(mock_object)}.to_not change{calls}
  end
end

如果没有必要绝对捕获所有例外,包括SystemExitNoMemoryErrorSignalException等(来自@ vito-botta的输入):

begin
  object.save!
rescue StandardError => e
  # Swallow "normal" exceptions and log it
end

StandardErrorrescue捕获的默认异常级别。

答案 1 :(得分:1)

来自rspec-mock的

module RSpec
  module Mocks
    class MockExpectationError < Exception
    end

    class AmbiguousReturnError < StandardError
    end
  end
end

你真的需要抓住Exception吗?你能不能抓住StandardError

捕获所有异常通常是一件坏事。

答案 2 :(得分:1)

我会像这样重构它:

class Thing do

  def self.method_being_tested!( object )

    # ... do some stuff

    return object.save
  end

end

如果要忽略save抛出的异常!打电话保存是没有意义的!首先。您只需调用save并相应地通知调用代码。