如何防止RSpec隐藏丢失的依赖项?

时间:2012-12-02 09:14:55

标签: ruby rspec

我有一个在运行时失败的Ruby程序,但是当我用RSpec测试它时可以正常工作。我知道错误的原因以及如何解决它(见下文),但我无法弄清楚如何构建一个证明错误存在的失败的RSpec测试。

想象一下以下Ruby:

foobar.rb

class Foobar
  attr_reader :fruit
  def initialize
    @fruit = Set.new ["Apple", "Banana", "Kiwi"]
  end
end

以上代码使用设置,但无法“要求'设置'”。这会导致它在运行时失败:

$ irb
> require './foobar.rb'
> f = Foobar.new
NameError: uninitialized constant Foobar::Set

在确定疏忽之前,我想构建一个简单的RSpec测试来证明这个bug。我的测试看起来像这样:

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 可用于它测试的代码,在我的情况下隐藏了一个bug。

我在测试中想到了“卸载/不需要”设置。我最接近的是这段代码:

Object.send(:remove_const, :Set)

这确实导致测试失败,但遗憾的是它还会阻止Set被未来的'require'再次加载,这意味着即使我在foobar中添加 require'set'后它仍然会失败.RB。

有没有更好的方法在运行时卸载gem?如果没有,我该怎么做才能使这个测试失败呢?

1 个答案:

答案 0 :(得分:3)

require 'rspec'

describe 'foobar.rb' do
  it "can instantiate Foobar" do
    `ruby -e 'Foobar.new' -r./foobar.rb`
    $?.exitstatus.should == 0
  end
end

适用于您提到的一个案例。也就是说,我不推荐这种方法。要涵盖引用类的所有情况,您需要以这种方式运行所有规范,因为类引用可能出现在代码中的任何位置。