Falling Leaves: the Ardes blog

Testing Singletons with Ruby

December 11th, 2006

Ian White

Testing a Singleton class is a bit tricker than you might expect. When testing, you typically need to reset the state of the objects in question in between tests. But this is something that a Singleton, by its nature, should never allow.

To solve this problem, you can make use of Ruby's open classes and add the following before your tests:

require 'singleton'

class <<Singleton
  def included_with_reset(klass)
    included_without_reset(klass)
    class <<klass
      def reset_instance
        Singleton.send :__init__, self
        self
      end
    end
  end
  alias_method :included_without_reset, :included
  alias_method :included, :included_with_reset
end

This code adds a class method when Singleton is mixed into your target class. This method reset_instance effectively removes the instance, so you can start again.

In your tests, when you need to start over with a Singleton, just send reset_instance to the singleton class. The following demonstrates this (note that the instance is a different object after MySingleton.reset_instance):

irb(main):026:0> MySingleton.instance
=> #<MySingleton:0x396fc>
irb(main):027:0> MySingleton.reset_instance
=> MySingleton
irb(main):028:0> MySingleton.instance
=> #<MySingleton:0x1cd04>