我有一个似乎特定于我的测试套件的问题。
我有一个模块,它在一个常量中包含一些默认值,如下所示:
module MyModule
DEFAULTS = {
pool: 15
}
def self.options
@options ||= DEFAULTS
end
def self.options=(opts)
@options = opts
end
end
module MyModule
class MyClass
def options
MyModule.options
end
def import_options(opts)
MyModule.options = opts
end
end
end
我允许程序在没有选项的情况下启动,或者用户可以指定选项。如果没有给出选项,我们使用默认值,但如果给出选项,我们使用它。示例测试套件如下所示:
RSpec.describe MyModule::MyClass do
context "with deafults" do
let(:my) { MyModule::MyClass.new }
it 'has a pool of 15' do
expect(my.options[:pool]).to eq 15
end
end
context "imported options" do
let(:my) { MyModule::MyClass.new }
it 'has optional pool size' do
my.import_options(pool: 30)
expect(my.options[:pool]).to eq 30
end
end
end
如果那些测试按顺序运行,很好,一切都过去了。如果它以反向运行(第二次测试首先进行),则第一次测试的池大小为30.
我没有“真实世界”的情况会发生这种情况,程序启动一次,就是这样,但我想相应地测试一下。有什么想法吗?
答案 0 :(得分:1)
@options
是该模块中的类变量。我不确定它在技术上是否正确,但这就是它的表现方式。作为实验,请在@options.object_id
中访问self.options
之前打印@options
。然后运行测试。您会看到在两种情况下都打印出相同的ID。这就是为什么当您的测试被翻转时,您得到30. @options ||= DEFAULTS
已经定义,因此@options
未将DEFAULTS
设置为$ cat foo.rb
module MyModule
DEFAULTS = {
pool: 15
}
def self.options
puts "options_id: #{@options.object_id}"
@options ||= DEFAULTS
end
def self.options=(opts)
@options = opts
end
end
module MyModule
class MyClass
def options
MyModule.options
end
def import_options(opts)
MyModule.options = opts
end
end
end
puts "pool 30"
my = MyModule::MyClass.new
my.import_options(pool: 30)
my.options[:pool]
puts
puts "defaults"
my = MyModule::MyClass.new
my.options[:pool]
。
$ ruby foo.rb
pool 30
options_id: 70260665635400
defaults
options_id: 70260665635400
运行它......
{{1}}
答案 1 :(得分:0)
您始终可以使用before(:each)
before(:each) do
MyModule.options = MyModule::DEFAULTS
end
旁注 - 可能是配置类。
类似的东西:
module MyModule
class Configuration
def initialize
@foo = 'default'
@bar = 'default'
@baz = 'default'
end
def load_from_yaml(path)
# :)
end
attr_accessor :foo, :bar, :baz
end
end
然后你可以添加这样的东西:
module MyModule
class << self
attr_accessor :configuration
end
# MyModule.configure do |config|
# config.baz = 123
# end
def self.configure
self.configuration ||= Configuration.new
yield(configuration)
end
end
最后,您将以更有意义的方式重置配置
before(:each) do
MyModule.configuration = MyModule::Configuration.new
end