mocking a singleton class

***** http://blog.frankel.ch/two-different-mocking-approaches

***** http://fruzenshtein.com/junit-and-mockito/

***** –> http://fruzenshtein.com/junit-and-easymock-cooperation/

http://www.jramoyo.com/2013/03/static-methods-and-unit-testing.html

http://stackoverflow.com/questions/2302179/mocking-a-singleton-class

A Singleton, by definition, has exactly one instance. Hence its creation is strictly controlled by the class itself. Typically it is a concrete class, not an interface, and due to its private constructor it is not subclassable. Moreover, it is found actively by its clients (by calling Singleton.getInstance() or an equivalent), so you can't easily use e.g. Dependency Injection to replace its "real" instance with a mock instance:

class Singleton {    private static final myInstance = new Singleton();    public static Singleton getInstance () { return myInstance; }    private Singleton() { ... }    // public methods}class Client {    public doSomething() {        Singleton singleton = Singleton.getInstance();        // use the singleton    }}

For mocks, you would ideally need an interface which can be freely subclassed, and whose concrete implementation is provided to its client(s) by dependency injection.

You can relax the Singleton implementation to make it testable by

  • providing an interface which can be implemented by a mock subclass as well as the "real" one
  • adding a setInstance method to allow replacing the instance in unit tests

Example:

interface Singleton {    private static final myInstance;    public static Singleton getInstance() { return myInstance; }    public static void setInstance(Singleton newInstance) { myInstance = newInstance; }    // public method declarations}// Used in productionclass RealSingleton implements Singleton {    // public methods}// Used in unit testsclass FakeSingleton implements Singleton {    // public methods}class ClientTest {    private Singleton testSingleton = new FakeSingleton();    @Test    public void test() {        Singleton.setSingleton(testSingleton);        client.doSomething();        // ...    }}

As you see, you can only make your Singleton-using code unit testable by compromising the "cleanness" of the Singleton. In the end, it is best not to use it at all if you can avoid it.

Update: And here is the obligatory reference to Working Effectively With Legacy Code by Michael Feathers.