Breaking Singletons for Unit Testing

The Lore

Singleton is a nice design pattern that proposes a way to make sure that an application only instantiates a single instance of a class, and that instance is the only one used throughout the code. That’s handy if you just want to get a reference to a common object and use it, regardless where in the code you are.

There are three reasons for using singleton:

* The class has very high instantiation costs
* The class models something for which there really is only one
* You need an easy way to discover a shared instance of a class

The first is, if a class instantiation takes a long time, burns a lot of CPU, or eats a lot of memory. The Singleton pattern can make sure you only pay that price once. The second case is when the thing your modelling really is just a single thing, like a card in a slot on the motherboard. The third reason is more for convenience. If you want different parts of your code to reference a common dependency, Singleton is an easy way to do that.

Ultimately Singleton is nothing new, it’s just an OO expression of something that’s globally visible. Really, the Singleton pattern is just The Industry’s expression that it never got past using global variables.

How It’s Done

There are pages that go into more depth on Singleton implementation, but really it boils down to, there are only two ways that you should instantiate singletons:

public class MySingleton
{
private static final MySingleton INSTANCE = new MySingleton();

private MySingleton() { }

public static MySingleton getInstance() { return INSTANCE; }

public String whoop() { return “whoop!”; }
}

The important features are:

* a private, no-argument constructor (only this class can instantiate itself)
* a static, final instance, which is The Instance that the entire system will use
* a public, static “getInstance” method that returns that instance. If you are bold, since the instance is static and final, you could just make INSTANCE public, but few programmers have the raw nerve to do that.

If you want a lazy-instantiated variation, do it this way:

public class MyLazySingleton
{
private MyLazySingleton() { }

private static class Singleton
{
private static final MyLazySingleton INSTANCE = new MyLazySingleton();
}

public static MyLazySingleton getInstance() { return Singleton.INSTANCE; }

public String whoop() { return “whoop!”; }
}

* The INSTANCE and it’s instantiation is pushed into an inner class, to ensure it will only get invoked when someone calls “getInstance”. The system won’t instantiate the INSTANCE if some code makes a reference to the class without calling getInstance.

Don’t do it that way, though. Most of the time singletons exist purely for convenience (and programmer laziness), so the extra lines of code to achieve lazy instantiation are just someone trying to look smart rather than any significant impact on system behavior.

The Problem

There are two large problems with Singletons implemented this way. The first is, since the getInstance method is static, any class that references the singleton has a hard, compile-time dependency on that particular implementation class. There’s no way to slip in an alternate or mock implementation for unit testing. If the singleton is big, hairy, unpleasant, or makes a call to an external system, there’s no way to get around it. That dependency is established at compile time, and can’t be broken for testing in isolation.

The other problem is, the class has a private constructor, so it can’t be subclassed. You’re stuck with one, and only one, implementation class, or else using a mock framework. (But it doesn’t really matter because there’s no way to slip an alternate implementation in there anyway.)

The Easy Way

It’s always my goal to be as lazy as possible while still looking smart, so I like the easy way of breaking singletons open to make then available for unit testing.

* make the constructor protected
* don’t make instance final
* add a setInstance() method with no arguments so a subclass can declare itself to be The Instance.

public class MyNiceSingleton
{
private static MySingleton INSTANCE = new MySingleton();

protected MySingleton() { }

public static MySingleton getInstance() { return INSTANCE; }

public void setInstance() { INSTANCE = this; }

public String whoop() { return “whoop!”; }
}

Now I can subclass the singleton and slip in an alternate implementation:

public class MyStubSingleton() extends MySingleton …

MyStubSingleton stub = new MyStubSingleton();
stub.setInstance();

MySingleton.getIntance().whoop(); // uses the stub

The Hard Way

OK so let’s say there’s someone on your team who is very literal minded, and blanches at the thought of deviating from the Singleton pattern AS STATED, even though you’re using singleton as a convenience rather than for hard technical requirements.

Reflection makes it easy to get in and break the singleton open. You just need to get at that INSTANCE field, and pop in the instance that you want. Since the constructor is private, you won’t be able to use a subclass, but you can pop in a mock object from one of the really nice mocking frameworks that are available today.

It’s pretty easy. Here’s one implementation that works. It looks for an INSTANCE field in the class itself, and then it looks in any inner classes. As soon as it finds one, it remembers the value of that field so you can restore it later. Then it drops in the implementation class that you want to use.

public class SingletonUsurper
{
protected Logger LOG = Logger.getLogger(SingletonUsurper.class);

static Field MODIFIERS;

static
{
try
{
MODIFIERS = Field.class.getDeclaredField(“modifiers”);
MODIFIERS.setAccessible(true);
}
catch (Exception e)
{
Logger.getLogger(SingletonUsurper.class).error(“failed”,e);
}
}

private final Class singletonClass;
private Field instanceField;
private final Object usurper;
private Object original;

/**
* constructor sets the class and usurper instance,
* then does the initial replacement
*/
public SingletonUsurper(Class clazz, Object usurper)
{
this.singletonClass = clazz;
this.usurper = usurper;
usurp();
}

/**
* put the usurper in place.
*

* You can call restore and then call this again.
*/
public void usurp()
{
try
{
instanceField = findInstanceField(singletonClass);

if ( instanceField == null )
{
instanceField = findInstanceInInternalClasses(singletonClass);
}

if ( instanceField == null )
{
LOG.warn(“no instance field found”);
}
else
{
setInstance();
}
}
catch (Exception e)
{
throw new RuntimeException(“failed”,e);
}
}

/**
* see if the given class has an INSTANCE (case-insensitive) field
*/
private Field findInstanceField(Class clazz)
{
Field field = null;

for ( Field f : clazz.getDeclaredFields() )
{
if ( “instance”.equals(f.getName().toLowerCase()) )
{
field = f;
break;
}
}

return field;
}

/**
* look in any internal classes for INSTANCE
*/
private Field findInstanceInInternalClasses(Class clazz)
{
Field field = null;

for ( Class c : clazz.getDeclaredClasses())
{
field = findInstanceField(c);

if (field != null) break;
}

return field;
}

/**
* set the INSTANCE field, even if it’s private and final
*/
private void setInstance() throws IllegalAccessException
{
instanceField.setAccessible(true);

MODIFIERS.setInt(instanceField,instanceField.getModifiers() & ~Modifier.FINAL);

original = instanceField.get(null);
instanceField.set(null,usurper);
}

/**
* restore the original INSTANCE
*/
public void restore()
{
try
{
if ( instanceField != null )
{
instanceField.set(null,original);
}
}
catch (Exception e)
{
throw new RuntimeException(“failed”,e);
}
}

}

The usage looks like this.

// with Mockito…
final MySingleton s = mock(MySingleton.class);
when (s.whoop()).thenReturn(“zing!”);

final SingletonUsurper usurper = new SingletonUsurper(MySingleton.class,s);

assertEquals(“zing!”, MySingleton.getInstance().whoop());

// replace the original instance
usurper.restore();

Note that I’d probably put the usurper construction in the @Before method, and the restore() in the @After method. But you get the idea.

Advertisements

Leave a comment

Filed under utility

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s