Introduction
One of the simplest patterns to learn and implement and one of the most controversial patterns is the Singleton pattern. If there is a need to control the access of a shared resource, Singleton pattern perfectly fits into the picture.
The problem arises when unit testing needs to be performed on it. Singleton leads to external dependencies, which is hard for unit testing.
For example: when we write a unit test, we fake our object such that it returns only the desired result.
In case of singleton, while faking we set the instance of singleton with our desired result, all other code instantiating singleton will have the same object. To overcome this, we can call a singleton from an interface.
Using Singleton from an Interface
First of all, extract an interface from the Singleton class and then apply Dependency Injection. We need interface for decoupling purpose and unit testing.
public interface ISingletonClass
{
string conn;
}
Singleton class implementing the interface:
namespace Singleton2DI
{
public class SingletonClass : ISingletonClass
{
private static readonly string conn;
static SingletonClass()
{
try
{
conn = "This is original class value";
}
catch (Exception ex)
{
throw ex;
}
}
public string Conn()
{
return conn;
}
}
}
Accessing singleton class from another class, the instance would then be passed to any objects that might trying to implement it through the property.
With DI, its just a matter of configuration, we can have single or multiple instances
public class SClass
{
private ISingletonClass _sc;
public ISingletonClass SC
{
get
{
if (_sc == null)
_sc = new SingletonClass();
return _sc;
}
set
{
_sc = value;
}
}
public virtual string ReturnConn()
{
return SC.Conn();
}
}
Points of Interest
Unit testing using MOQ framework, we can easily pass a fake object for unit tests, without bothering for an extra instance to haunt...
[TestMethod()]
public void ReturnConnTest()
{
SClass target = new SClass();
string expected = "This is MOQ class";
string actual;
Mock<SClass> moqClass = new Mock<SClass>();
moqClass.Setup(mc => mc.ReturnConn()).Returns(expected);
target = moqClass.Object;
actual = target.ReturnConn();
Assert.AreEqual(expected, actual);
}
A simple guy who loves the software development and enjoys being involved in the software development / creation process and looking forward to know more and more in this magnificent field.
I have worked in various areas in software process and gained a solid experience during my 7 years professional tenure in software designing, development and management.