为什么必须在块中包装对象属性以检查它是否引发错误?

时间:2018-02-22 14:10:34

标签: ruby rspec

我正在阅读this教程。在“动态属性”部分中,它告诉您将最小的规范包装在一个块中,以检查是否覆盖了method_missing在虚构属性上引发NoMethodError。我正在使用RSpec,docs显示完全相同的模式:

RSpec.describe "calling a missing method" do
  it "raises" do
    expect { Object.new.foo }.to raise_error(NameError)
  end
end

我的规格:

传递规范

it "raises a method missing error if attribute is not present" do
  expect { coin.imaginary_attribute }.to raise_error(NoMethodError)
end

规格失败

it "raises a method missing error if attribute is not present" do
  expect(coin.imaginary_attribute).to raise_error(NoMethodError)
end 

错误讯息:

NoMethodError:
      undefined method `imaginary_attribute'

我在不使用块的情况下对其进行了测试,正如预期的那样,测试失败了。它背后的原因是什么?

1 个答案:

答案 0 :(得分:4)

将代码包装在块中,以便expect可以控制何时调用代码。在伪红宝石中,它看起来像这样:

def expect(&block)
  begin
    block.call
  rescue => ex
    save_exception_for_assertions(ex)
  end
end

这有两件事:

  1. 截取异常,以便匹配器可以使用
  2. 确保异常不影响规范执行(因为预期)。
  3. 相比之下,您尝试的其他变体

     expect(coin.imaginary_attribute).to raise_error(NoMethodError)
    
    在调用coin.imaginary_attribute之前评估

    expect(因为这里它是方法调用中的常规参数)。因此expect没有机会拦截异常,并且您的规范崩溃了。