2009-11-08 26 views
4

我得到的代码只需要在特定版本的ActiveRecord上运行(解决旧AR库上的一个错误)。此代码测试ActiveRecord :: VERSION常量的值以查看是否需要运行。我可以使用rspec mocks来存储版本常量吗?

有没有一种方法来模拟rspec中的那些常量,这样我就可以测试代码路径而不依赖在测试机器上安装正确的ActiveRecord gem?

回答

10

我最后写一个辅助方法,让在执行的代码块我重写常量:

def with_constants(constants, &block) 
    constants.each do |constant, val| 
    Object.const_set(constant, val) 
    end 

    block.call 

    constants.each do |constant, val| 
    Object.send(:remove_const, constant) 
    end 
end 

把这个代码在你spec_helper.rb文件后,就可以使用如下:

with_constants :RAILS_ROOT => "bar", :RAILS_ENV => "test" do 
    code goes here ... 
end 

希望这适用于你。

+0

工程就像一个魅力,谢谢。 –

2

德鲁·奥尔森,我把你的想法,并提出了一些修改,添加范围界定:

class Object 
    def self.with_constants(constants, &block) 
    old_constants = Hash.new 
    constants.each do |constant, val| 
     old_constants[constant] = const_get(constant) 
     silence_stderr{ const_set(constant, val) } 
    end 

    block.call 

    old_constants.each do |constant, val| 
     silence_stderr{ const_set(constant, val) } 
    end 
    end 
end 

把这个代码在功能/支持/ with_constants.rb文件后,就可以使用如下:

MyModel.with_constants :MAX_RESULT => 2, :MIN_RESULT => 1 do 
    code goes here ... 
end 
+0

使用'''Kernel :: silence_warnings {const_set(constant,val)}''而不是'''silence_stderr {const_set(constant,val)}''' –

1

添加救援块对于确保在测试套件中的其他测试中恢复常量非常重要!

class Object 
    class << self 
    def with_constants(constants, &block) 
     old_constants = Hash.new 
     constants.each do |constant, val| 
     old_constants[constant] = const_get(constant) 
     Kernel::silence_warnings { const_set(constant, val) } 
     end 

     error = nil 
     begin 
     block.call 
     rescue Exception => e 
     error = e 
     end 

     old_constants.each do |constant, val| 
     Kernel::silence_warnings { const_set(constant, val) } 
     end 

     raise error unless error.nil? 
    end 
    end 
end 

通常

describe "#fail" do 

    it "should throw error" do 
    expect { 
     MyModel.with_constants(:MAX_RESULT => 1) do 
     # code with throw error 
     end 
    }.to raise_error 
    end 

end 
相关问题