为获救异常编写 RSpec 测试
Writing RSpec Test for Rescued Exception
我有这样的代码:
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 时给出版本。例如,在我的项目中,水豚 gem 将不存在,所以这有效:
Empiric.gem_version("capybara")
当我说 "works" 时,我的意思是它引发了适当的异常。我正在尝试为此创建一个 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.?) but that solution didn't seem to work at all for me. I also looked at this (), which also offers little in the way of help for me. Likewise for this (Rspec: testing a rescue) and this (Using RSpec how can I test the results of a rescue exception block) and this (Rspec: Test rescue block)。
需要说明的是,我不是在 Rails 环境中操作。这是一个独立的 gem 我正在写。
好的,所以这里的答案非常简单(感谢@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 --带有不同的消息 -- 正在发生。
我很想删除这个问题,因为我显然犯了一个愚蠢的错误。但我觉得这个错误的背景对于其他正在研究这个问题的人来说可能足够有趣。如果版主不同意并认为应该删除,请不要担心。否则,我的愚蠢就会被供奉给所有人看。
我有这样的代码:
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 时给出版本。例如,在我的项目中,水豚 gem 将不存在,所以这有效:
Empiric.gem_version("capybara")
当我说 "works" 时,我的意思是它引发了适当的异常。我正在尝试为此创建一个 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.?) but that solution didn't seem to work at all for me. I also looked at this (
需要说明的是,我不是在 Rails 环境中操作。这是一个独立的 gem 我正在写。
好的,所以这里的答案非常简单(感谢@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 --带有不同的消息 -- 正在发生。
我很想删除这个问题,因为我显然犯了一个愚蠢的错误。但我觉得这个错误的背景对于其他正在研究这个问题的人来说可能足够有趣。如果版主不同意并认为应该删除,请不要担心。否则,我的愚蠢就会被供奉给所有人看。