我有一个 Ruby 程序在运行时失败,但是当我用 RSpec 测试它时可以工作。我知道错误的原因以及如何修复它(见下文),但我不知道如何构建一个失败的 RSpec 测试来证明错误的存在。
想象一下下面的 Ruby:
foobar.rb
class Foobar
attr_reader :fruit
def initialize
@fruit = Set.new ["Apple", "Banana", "Kiwi"]
end
end
上面的代码使用了Set,但它没有“要求 'set'”。这会导致它在运行时失败:
$ irb
> require './foobar.rb'
> f = Foobar.new
NameError: uninitialized constant Foobar::Set
在修复疏忽之前,我想构建一个简单的 RSpec 测试来证明这个错误。我的测试如下所示:
foobar_spec.rb
require 'rspec'
require './foobar.rb'
describe Foobar do
it "can be initialized" do
expect { Foobar.new }.to_not raise_error
end
end
运行测试,我惊讶地发现它通过了:
$ rspec foobar_spec.rb
.
Finished in 0.00198 seconds
1 example, 0 failures
经过一番挖掘,我了解到 RSpec 会为自己加载Set。这导致Set可用于它测试的代码,在我的例子中隐藏了一个错误。
在我的测试中,我有“卸载/不需要”设置的想法。我最接近的是这段代码:
Object.send(:remove_const, :Set)
这确实会导致测试失败,但不幸的是,它也阻止了 Set 被未来的“require”再次加载,这意味着即使我在 foobar.rb 中添加了require 'set' ,它仍然会失败。
有没有更好的方法在运行时卸载 gem?如果没有,我该怎么做才能使这个测试失败?