Rspec没有捕捉到有目的的失败

时间:2015-12-29 23:46:34

标签: ruby exception rspec

我正在尝试检查我的一个类方法是否响应带有异常的无效输入,但是Rspec没有它。

我的班级档案:

class WhateverClass
  def run(options)
    if options['input'].nil? || options['input'].empty?
      fail ArgumentError, 'No input object provided in configuration.'
    end
  end
end

我的Rspec测试:

RSpec.describe WhateverClass do
  it 'should raise an ArgumentError when provided invalid input' do
    invalid_input = { 'nonsense' => 'here' }
    expect(WhateverClass.new.run(invalid_input)).to raise_error(ArgumentError)
  end
end

运行上述测试的结果如下:

1) WhateverClass should raise an ArgumentError when provided invalid input
   Failure/Error: expect(WhateverClass.new.run(invalid_input)).to raise_error(ArgumentError)
   ArgumentError:
     No input object provided in configuration.
   # ./whatever_class.rb:9:in `run'
   # ./spec/whatever_class_spec.rb:14:in `block (2 levels) in <top (required)>'
Finished in 0.00048 seconds (files took 1.51 seconds to load)
1 example, 1 failure

=============================================== ====

请注意,如果我这样做:

RSpec.describe WhateverClass do
  it 'should raise an ArgumentError when provided invalid input' do
    expect{ fail ArgumentError }.to raise_error(ArgumentError)
    invalid_input = { 'nonsense' => 'here' }
    expect(WhateverClass.new.run(invalid_input)).to raise_error(ArgumentError)
  end
end

第一个预期通过,但第二个预期失败。

如何让此测试正常运行?

2 个答案:

答案 0 :(得分:6)

原来是将其改为:

expect(WhateverClass.new.run(invalid_input)).to raise_error(ArgumentError)

为:

expect { WhateverClass.new.run(invalid_input) }.to raise_error(ArgumentError)

解决了这个问题。希望这有助于其他人。

答案 1 :(得分:2)

切换到expect的块形式是正确的做法,但我认为一些解释是值得的。

当你说:

expect(WhateverClass.new.run(invalid_input)).to ...
你有效地说:

x = WhateverClass.new.run(invalid_input)
expect(x).to ...

所以WhateverClass.new.run(invalid_input)将在构建expect的参数时进行评估(即 expect之前的)。这意味着在expect可以执行任何操作之前引发异常。

当你说:

expect { WhateverClass.new.run(invalid_input) }.to ...

你给expect一个块({ WhateverClass.new.run(invalid_input) }),expect将在设置了异常处理后执行该块。这意味着在expect的异常处理程序到位时将引发异常,因此异常将被捕获,并且to方法将返回expect的返回值。< / p>