There are a few issues that need to be taken in account when
mocking Singleton classes.
:arrow: Mocking the constructor
:arrow:
Mocking instances
Suppose we have a
singleton class called
singleton Singleton that has a foo() method that we want to
mock.
The method will be called in the code as follows:
Singleton.GetInstance().foo()
The Singleton might have a static initialization of itself:
static private Singleton instance = new Singleton();
public Singleton GetInstance() { return instance;}
We would normally mock using:
Mock singletonMock =
MockManager.Mock(typeof(Singleton),false);
singletonMock.ExpectCall("foo");
:!: We are sending
false to tell TypeMock that we don't want our constructors to be mocked. This will allow our static initialization to run, so our Singleton code:
static private Singleton instance = new Singleton(); will run.
(See
Mocking Constructors on how to mock the constructor but to keep the static initialization)
:!: But this won't work and a strange behaviour will appear. When we run a test alone it will work, but when we run a suite of tests they will start failing. We will find out that TypeMock, mocks the singleton only for the first test!
If we read the documentation, the
MockManager.Mock method will mock the
next creation of a Singleton object but if the Singleton exists already, for example in a previous test, the existing object will
not be mocked. So the Above code will not work.
:idea: The correct way to mock singletons is to use the MockAll method:
Mock singletonMock =
MockManager.MockAll(typeof(Singleton),false);
This will mock existing objects as well, and because there is only one singelton object in the domain, we will be mocking the correct object.