The Effective Java has the following statement on unit testing singletons
Making a class a singleton can make it difficult to test its clients, as it’s im
The problem isn't testing singletons themselves; the book is saying that if a class you are trying to test depends on a singleton, then you will likely have problems.
Unless, that is, you (1) make the singleton implement an interface, and (2) inject the singleton to your class using that interface.
For example, singletons are typically instantiated directly like this:
public class MyClass
{
private MySingleton __s = MySingleton.getInstance() ;
...
}
MyClass
may now be very difficult to automatedly test. For example, as @Boris Pavlović notes in his answer, if the singleton's behaviour is based on the system time, your tests are now also dependent on the system time, and you may not be able to test cases that, say, depend on the day of the week.
However, if your singleton "implements an interface that serves as its type" then you can still use a singleton implementation of that interface, so long as you pass it in:
public class SomeSingleton
implements SomeInterface
{
...
}
public class MyClass
{
private SomeInterface __s ;
public MyClass( SomeInterface s )
{
__s = s ;
}
...
}
...
MyClass m = new MyClass( SomeSingleton.getInstance() ) ;
From the perspective of testing MyClass
you now don't care if SomeSingleton
is singleton or not: you can also pass in any other implementation you want, including the singleton implementation, but most likely you'll use a mock of some sort which you control from your tests.
BTW, this is NOT the way to do it:
public class MyClass
{
private SomeInterface __s = SomeSingleton.getInstance() ;
public MyClass()
{
}
...
}
That still works out the same at run-time, but for testing you are now again dependent on SomeSingleton
.