FitNesse uses a single VM to run all pages in a test suite. This causes issues with static variables. They should be reset after each test page.
There are also issues with singletons. They, too, should be reset after each test page has run. So… you have to hunt down and reset each and every singleton in the system. As I was thinking about this, an approach occurred to me that will help with this, as well as making your singletons visible and easily findable.
Marking Singletons
I’ll start by making an interface to mark singletons:
public interface Singleton
{
}
Now I can mark each singeton, for example:
public class PrintQueue implements Singleton
{
private static PrintQueue instance = null;
public static PrintQueue getInstance () {
if (instance == null) {
instance = new PrintQueue();
}
return instance;
}
private PrintQueue() {
//....
}
}
So that makes the singletons easy to find.. just pull up implementors of Singleton.
Managing Singletons
Next I want to actively manage them. I’ll need to keep track of them:
public class SingletonManager
{
private static List singletons = new ArrayList();
public static void registerSingleton (Singleton aSingleton) {
if (singletons.contains(aSingleton)) return;
singletons.add(aSingleton);
}
}
And I need to hook our singletons into the manager:
public class PrintQueue implements Singleton
{
public static getInstance () {
if (instance == null) {
instance = new PrintQueue();
SingletonManager.registerSingleton(instance);
}
return instance;
}
}
Now I have a lists of all the singletons in the system. This lets me do interesting things.
Resetting Singletons
The first thing (maybe the only thing… and it’s enough… it’s the whole reason for this article) is to reset all the singletons.
public class SingletonManager
{
public static void reset () {
Iterator singetonIt = singetons.iterator();
while (singletonIt.hasNext()) {
Singleton aSingleton = (Singleton)singletonIt.next();
aSingleton.reset();
}
}
}
Singleton needs a reset method now:
public interface Singleton
{
void reset();
}
which needs to be implemented:
public class PrintQueue implements Singleton
{
public void reset() {
// do anything required to cleanup
instance = null;
}
}
Cleaning Up
Now I can use this reset facility from a fixture on the TearDown page on my test suites to reset all my singletons after each test page.
Of course, a better approach would be to not use singletons.
Tags: code fit java