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

标签 ruby rspec

我正在阅读 this教程。在“动态属性”部分中,它告诉您将您的 minitest 规范包装在一个 block 中,以检查覆盖的 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'

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

最佳答案

您将代码包装在 block 中,以便 expect 可以控制何时调用您的代码。在伪 ruby 中,它看起来像这样:

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

这做了两件事:

  1. 拦截异常,以便它可用于匹配器
  2. 确保异常不会影响规范执行(因为它是预期的)。

相比之下,您尝试的其他变体

 expect(coin.imaginary_attribute).to raise_error(NoMethodError)

coin.imaginary_attribute 在调用 expect 之前进行评估(因为这里它是方法调用中的常规参数)。所以 expect 没有机会拦截异常,你的规范崩溃了。

关于ruby - 为什么必须将对象属性包装在 block 中以检查它是否引发错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48929511/

相关文章:

javascript - 如何使用某种条件根据用户信息显示帖子

ruby-on-rails - Cucumber Stories 的 session 变量

ruby-on-rails - 不推荐在模板名称中传递模板处理程序是什么意思。意思是?

rspec - 如何在RSpec模拟/ stub 中使用不同的参数值?

ruby - 如何使用 rspec 在 ruby​​ 中模拟 super?

ruby-on-rails - 从 rspec 中的助手规范访问 session

ruby - Sinatra:指定使用多个应用程序时搜索路线的顺序?

ruby-on-rails - 为什么我本地编辑的 gem 中的某些方法没有出现在我的 Rails 控制台中?

ruby-on-rails - 无法安装 gems,因为 "undefined method ` invoke_with_build_args' for nil :NilClass"

ruby-on-rails - 使用 Nokogiri 解析 HTML - The Ruby/Rails Way