Sunday 29 November 2009

Unit Testing Singletons

Much have been said about the singleton pattern, a short visit to Google shows that its mainly about why not to use them. However, for some reason, in all projects I have seen up to date I found quite a few usages of this patten. In fact in most places, this pattern is over used extensible. I'm guessing this is mainly due to the ease of implementation, and the fact that in most systems one can find several classes which are only instantiated once. (i.e. we only need a single instance in the system)

This post is NOT about whether singleton are good or bad, for me that's not an interesting question. In realizing that most people use them, my goal in this post is just to show some useful tips on how to actually handle them during tests .

But first lets look at a common implementation of the singleton (taken from Wikipedia):

public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();

static Singleton()
{
}

private Singleton()
{
}

public static Singleton Instance
{
get { return instance; }
}
}
This implementation poses 2 testing problems that need to be addressed:

  1. A private constructor - When writing tests, our main goal is to make them independent. Therefore we prefer that each test case will work on a different instance to avoid any chance one test will affect another.
  2. The static Instance method - its a valid assumption that much of the code will access the singleton using the Instance method. And it being a static method makes it harder to inject a fake instead of the singleton object.

There are several approaches for bypassing these issues:

1) Use reflection - either to create a new instance each test, or maybe to clear the created instance at the end of the test. (a good summary can be found here).

2) Decouple the business logic, from the creation logic - and test the business logic separately. A IOC container is a common technique for doing this, but a simple factory will do just as well.

3) expose some special method for testing, allowing to tweak the internal field - a simple setter sometimes goes a long way.

and I'm sure that there are more ways. to skin this cat.

I, however, prefer to leverage my tools as much as a I can. Specifically lets see how the Isolator (yeah a big surprise) can help me on this.

Scenario one - Faking a Singleton Behavior

You need to test a class which uses the singleton. During the test you need the singleton to behave in a manner which is very hard to simulate using the real production code (of the singleton). you would like to use a mock however its hard to inject the mock into the code since the static Instance method is had to mock using conventional approaches. In this case you can use the Isolator for setting a fake behavior and mocking the static Instance Method. Here is an example:

[TestMethod]
public void FakingSingleton()
{
// Create a fake instance
var fakeSingleton = Isolate.Fake.Instance<Singleton>();
// Set the faked behavior
Isolate.WhenCalled(() => fakeSingleton.SomeMethod()).WillReturn(7);
// Inject the fake into your production code
Isolate.WhenCalled(() => Singleton.Instance).WillReturn(fakeSingleton);
// Execute the test
var actual = Singleton.Instance.SomeMethod();
Assert.AreEqual(7, actual);

}

Scenario two - Testing the singleton class

Using the same technique we would like to test the singleton internal logic. However since the constructor is private its harder to created new instance each test. again Isolator can be used:

[TestMethod]
[Isolated]
public void SomeMethodTest()
{
//Just a cool way to create a regular instance instead of using reflection.
var fakeSingleton = Isolate.Fake.Instance<Singleton>(Members.CallOriginal);

//use this if you want your test to look similar to production code
Isolate.WhenCalled(() => Singleton.Instance).WillReturn(fakeSingleton);

var actual = Singleton.Instance.SomeMethod();
Assert.AreEqual(5,actual);
}

While all this examples are written for the .Net platform, one can achieve basically the same in Java using PowerMock and even (to some extent) in C++ using MockitNow.

2 comments:

Markus Gärtner said...

Almost always I use the Substituted Singleton pattern from xUnit Test Patterns to test singletons.

The dynamic is easy:
- make the singleton constructor and field protected
- bring in a test-specific subclass from the singleton, where you can manipulate the instance field to your needs and some setters for class specific behavior

Basically that's all. No need for any mocking framework.

Lior Friedman: said...

Hi Markus,
Agreed, you don't NEED a framework for this.

However if you are using Isolator, I think the technique here requires less code (which hopefully means less work). and you get the(small) added bonus that your production code stays as it was meant to be.

Also, I think that basically you can do anything manually, and thats not a bad thing. However, a good framework should be a time saver.

 
Design by Free WordPress Themes | Bloggerized by Lasantha - Premium Blogger Themes | Walgreens Printable Coupons