如何测试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