如何测试Singleton类?
我正在使用RSpec并且想要多次测试Singleton类的构造函数。
我怎样才能做到这一点?
最好的祝福
看看http://blog.ardes.com/2006/12/11/testing-singletons-with-ruby :
require 'singleton' class <
Singleton类基本上就是这样做的
def self.instance @instance ||= new end private_class_method :new
所以你可以通过使用send调用private方法来完全绕过memoization
let(:instance) { GlobalClass.send(:new) }
这种方式的一个很好的好处是,由于测试运行,没有修改全局状态。
从这个答案可能是一个更好的方法:
let(:instance) { Class.new(GlobalClass).instance }
这将创建一个inheritance自GlobalClass
的匿名类,所有类级实例变量都存储在其中。然后在每次测试后抛弃它,使GlobalClass
保持不变。
# singleton_spec.rb require "singleton" class Global include Singleton def initialize puts "Initializing" end end describe Global do before do Singleton.__init__(Global) end it "test1" do Global.instance end it "test2" do Global.instance end end % rspec singleton_spec.rb -fd Global Initializing test1 Initializing test2
我见过的一种模式是将单例作为真实类的子类。 您在生产代码中使用Singleton版本,但是用于测试的基础(非单例)类。
例:
class MyClass attr_accessor :some_state def initialize @some_state = {} end end class MySingletonClass < MyClass include Singleton end
...但我正在寻找一种更好的方式。
我的部分问题是我正在使用JRuby并挂钩到全局的Java System Preferences。 剩下的我想我可以重构一下。
人们使用单身人士的一个原因是因为“全球变量很糟糕,不能吗?” 单例是一个全局变量,在名称空间中隔离,并具有惰性实例化。 考虑一个真正的全局变量是否可以简化事情,特别是如果您不需要延迟实例化。
将其重构为可以多次构造的类。 这具有从类中移除Singleton性质的副作用(有些人会说有益)。
再看看它:你发现需要不止一次调用构造函数。 为什么该类只构造一个实例? Singleton提供什么好处?
RSpec是否允许您执行预测试操作? 是这样,您可以向静态类添加另一个方法,清除构造函数中完成的任何操作。 然后在每次测试之前调用它。
您可以简单地为每个规范创建一个新的块并阻止it
。 将您的规范细分为可测试单元。 使用“之前”和“之后”设置并清除您执行的任何操作。
对每个块执行before(:each)
和after(:each)
it
。