4

我有一个我预计会失败的 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 异常,因为那是糟糕的设计(应该为代码编写测试,永远不应该为测试编写代码)。但我也无法检查异常是否是我希望它捕获的任何特定类型,因为我希望它能够捕获在正常生产环境中可能引发的任何内容。

一定有人在我之前遇到过这个问题!请帮我找到解决方案。

4

3 回答 3

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

如果不需要绝对捕获所有异常,包括,SystemExit等(来自@vito-botta 的输入):NoMemoryErrorSignalException

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

StandardError是被捕获的默认异常级别rescue

于 2013-12-19T11:24:38.637 回答
1

我会像这样重构它:

class Thing do

  def self.method_being_tested!( object )

    # ... do some stuff

    return object.save
  end

end

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

于 2013-06-20T07:08:50.293 回答
1

来自 rspec 模拟:

module RSpec
  module Mocks
    class MockExpectationError < Exception
    end

    class AmbiguousReturnError < StandardError
    end
  end
end

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

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

于 2011-09-16T02:45:54.030 回答