我得到的代码只需要在特定版本的ActiveRecord上运行(解决旧AR库上的一个错误)。此代码测试ActiveRecord :: VERSION常量的值以查看是否需要运行。我可以使用rspec mocks来存储版本常量吗?
有没有一种方法来模拟rspec中的那些常量,这样我就可以测试代码路径而不依赖在测试机器上安装正确的ActiveRecord gem?
我得到的代码只需要在特定版本的ActiveRecord上运行(解决旧AR库上的一个错误)。此代码测试ActiveRecord :: VERSION常量的值以查看是否需要运行。我可以使用rspec mocks来存储版本常量吗?
有没有一种方法来模拟rspec中的那些常量,这样我就可以测试代码路径而不依赖在测试机器上安装正确的ActiveRecord gem?
我最后写一个辅助方法,让在执行的代码块我重写常量:
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
希望这适用于你。
德鲁·奥尔森,我把你的想法,并提出了一些修改,添加范围界定:
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
使用'''Kernel :: silence_warnings {const_set(constant,val)}''而不是'''silence_stderr {const_set(constant,val)}''' –
添加救援块对于确保在测试套件中的其他测试中恢复常量非常重要!
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
使用RSpec 2.11,不断磕碰支持开箱即用stub_const
:
describe "stub_const" do
it "changes the constant value for the duration of the example" do
stub_const("Foo::SIZE", 10)
expect(Foo::SIZE).to eq(10)
end
end
见迈伦·马斯顿公布更多细节:
工程就像一个魅力,谢谢。 –