我有这样的代码:
module Empiric
module_function
def gem_version(name)
Gem.loaded_specs[name].version
rescue NoMethodError
raise NoMethodError, "No gem loaded for #{name}"
end
end
此功能旨在查找已加载的宝石并提供版本(如果找到该宝石)。例如,在我的项目中,“水豚”宝石将不存在,因此可以正常工作:
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上下文中操作。这是我正在编写的独立的宝石。
答案 0 :(得分:1)
好的,所以这里的答案非常简单(感谢@katafrakt指出)。我会在这里回答,因为我认为这很有趣。
问题在我的测试中:
it "indicates if a dependent gem is not found" do
expect {
Empiric.get_version("capybara")
}.to raise_error NoMethodError
end
注意,我打的是get_version
,而不是gem_version
。但是...那为什么测试没有表明这一点呢?至少失败了,这是我所期望的。
我发现问题的唯一方法是添加异常提供的消息。发挥作用:
...
.to raise_error NoMethodError, "No gem loaded for capybara."
然后该执行告诉我,没有定义get_version
方法。具体来说,我得到了这个:
expected NoMethodError with "No gem loaded for capybara",
got #<NoMethodError: undefined method `get_version' for Empiric:Module>
显然,将测试固定为调用正确的方法可以解决问题。但是还不清楚的是为什么当我明确地调用一个不正确的方法时,测试最初指示为通过。不仅是一种错误的方法,而且是一种不存在的方法。我的代码中根本没有get_version
方法。
但是请注意,我首先要挽救“ NoMethodError”。所以也许是这种情况?也许get_version
本身是一个NoMethodError的事实被测试的行为所吞没了?只是当我为 my 异常输入特定消息时,才迫使RSpec意识到发生了 actual NoMethodError(带有不同的消息)。 / p>
由于我明显犯了一个白痴的错误,所以我很想删除这个问题。但是我觉得对于其他人来说,这个错误的背景可能会很有趣。如果主持人不同意并认为应删除此内容,则无需担心。否则,我的愚蠢就会被所有人看到。