Sunday, March 1, 2009

Mocking singletons and Factories

Mocking singletons ., factories may not be that obvious.

public class Singleton {
private Singleton instance = new Singleton ();
public static Singleton getInstance() {
return instance;
}
}

@Test
public void testSingleton() {
Field instanceField = Singleton .class.getField("instance");
instanceField.setAccessible(true);
Singleton realSingleton = instanceField.get(null);
Singleton mockSingleton = EasyMock.createMock(Singleton .class);
try {
instanceField.set(null, mockSingleton);
// now do your testing, Singleton.getInstance() should now return the mock
} finally {
instanceField.set(null, reallSingleton);
instanceField.setAccessible(false);
}
}

This is fairly hacky, not robust to changes in the singleton class, won't work with a security manager, and it may not work well in the case where the field is instantiated in a static initializer and other fields use that instance when they are initialized. But it probably will work in many cases.

2 comments:

Anonymous said...

thanks for the example--it was not obvious to me how to do it, and most of the search hits I got simply pointed out that mocking a static method wasn't possible in easymock--ignoring your suggesting that you simply inject the mock into the instance :)

[I did have to use getDeclaredField instead of simply getField for some reason]

Lavnish said...

glad i could help