【发布时间】:2019-10-29 20:54:50
【问题描述】:
我有这样的代码:
module Empiric
module_function
def gem_version(name)
Gem.loaded_specs[name].version
rescue NoMethodError
raise NoMethodError, "No gem loaded for #{name}"
end
end
这旨在查找已加载的 gem 并在找到 gem 时给出版本。例如,在我的项目中,Capybara gem 将不存在,所以这是可行的:
Empiric.gem_version("capybara")
当我说它“有效”时,我的意思是它引发了适当的异常。我正在尝试为此创建一个 RSpec 测试,我想出了这个:
it "indicates if a dependent gem is not found" do
expect {
Empiric.get_version("capybara")
}.to raise_error NoMethodError
end
测试通过了……但是,测试覆盖率表明我的raise 部分没有被覆盖。
然而,如果我将上面的测试改为.not_to raise_error NoMethodError,测试就会失败。正如它应该。请注意,我将其更改为“not_to”而不是“to”。所以这向我表明,测试实际上是在识别产生了错误。
这是否与我专门拯救错误的事实有关?因为rescue 行显示它已包含在测试覆盖率报告中,但raise 语句没有,即使我已经验证它确实发生了。
在尝试回答我自己的问题时,我确实遇到了这个问题 (How to write down the rspec to test rescue block.?),但该解决方案似乎对我根本不起作用。我还查看了这个 (How do I test the rescue block of a method with rspec mocks 3.3),它对我的帮助也很少。对于这个 (Rspec: testing a rescue) 和这个 (Using RSpec how can I test the results of a rescue exception block) 和这个 (Rspec: Test rescue block) 也是如此。
为了清楚起见,我不是在 Rails 上下文中操作。这是我正在编写的独立 gem。
【问题讨论】:
-
在第一步中,我将使用
expect { ... }.to raise_error NoMethodError, "No gem loaded for capybara"检查异常附加了哪些消息。也许这是报道记者的一个错误? -
有趣。当我尝试从 rspec 得到这个时:
expected NoMethodError with "No gem loaded for capybara", got #<NoMethodError: undefined methodget_version' for Empiric:Module>`。这绝对是奇怪的,因为我可以在测试之外毫无问题地调用该方法并且不添加异常消息,所以我没有收到关于根本找不到该方法的错误。我使用的覆盖工具是 SimpleCov。 -
嘿,这是
get_versionvsgem_version;) -
拯救 NoMethodError 并不是一个好主意,因为它是一个很好的掩盖错误的方法。相反,您应该使用
Hash#fetch和救援 KeyError 或安全运算符.&。 -
使用
Gem.loaded_specs.fetch(name).version和rescue KeyError或安全运算符Gem.loaded_specs.fetch(name).&version并检查 nil。