How to Mock Singletons in 3 Simple Ways

Want to mock Singletons?

Here are 3 simple ways to mock a Singletons.

1. Use MockAll

When the static constructor is not mocked just use MockAll

Mock theSingletonMock = MockManager.MockAll(typeof(Singleton), Constructor.StaticNotMocked);

or to mock the constructor

Mock theSingletonMock = MockManager.MockAll(typeof(Singleton), Constructor.NotMocked);

Remember that you can only MockAll once until all mocks are verified/cleared. To retrieve the mock simply use:

Mock theSingletonMock = MockManager.GetMockAll(typeof(Singleton));

2. Use a MockObject

When the static constructor needs to be mocked we can return a mocked object whenever Instance is called 

// make sure that all constructors are mocked MockManager.MockAll(typeof(Singleton), Constructor.Mocked); // create mocked singleton object 🙂 MockObject theSingletonMock = MockManager.MockObject(typeof(Singleton), Constructor.Mocked); // return our mocked singleton theSingletonMock.ExpectGetAlways("Instance", theSingletonMock.Object);

Note: This will only work when the static constructor is mocked.
Also watch out for beforeFieldInit issues.

3. Set the instance Field

Another way to mock static constructors of singletons is to set the instance field.

MockObject theSingletonMock = MockManager.MockObject(typeof(Singleton), Constructor.Mocked); ObjectState.SetField(typeof(Singleton), "instance", theSingletonMock.Object);

remember that you are changing a field so it is best to reset the field after the test. Here is one way.

MockObject theSingletonMock = MockManager.MockObject(typeof(Singleton), Constructor.Mocked); object keptSingleton = ObjectState.GetField(typeof(Singleton), "instance"); try { ObjectState.SetField(typeof(Singleton), "instance", theSingletonMock.Object); // the test... } finally { ObjectState.SetField(typeof(Singleton), "instance", keptSingleton); }

Note: As before this will only work when the static constructor is mocked.

One comment

Add Comment

Required fields are marked *. Your email address will not be published.