C#

Unity Singleton / Unit testing / Mocking

It’s been a while since I did a blog post (that is something I aim to fix), but just for now here is a small one.

The other day, I was confronted with a class that I had to test/mock, and it had this hardcoded dependency on a IOC container item (we are using the Unity application block) in its constructor

public interface ISecurityProvider
{
    IList Privileges { get; }
}

public class SecurityProvider : ISecurityProvider
{
    private SecurityContext context;

    public SecurityProvider()
    {
        context = IOCManager.Instance.Container.Resolve();
    }

    public IList Privileges
    {
        get { return context.Privileges; }
    }
}

Where the SecurityContext class looks like this

public class SecurityContext
{
    public SecurityContext(List privileges)
    {
        this.Privileges = privileges;
    }

    public List Privileges { get; set; }
}

And the IOC manager looks somethi

public class IOCManager
{
    private static Lazy instance = new Lazy(()=> new IOCManager());

    private IOCManager()
    {
            Container = new UnityContainer();
    }

    static IOCManager()
    {

    }

    public static IOCManager Instance
    {
        get { return instance.Value; }
    }

    public UnityContainer Container { get; set; }
}

And the IOC configuration looks like this

List privileges = new List();
privileges.Add("CanTrade");
privileges.Add("CanPrice");

SecurityContext sc = new SecurityContext(privileges);

IOCManager.Instance.Container.RegisterInstance(sc, new ContainerControlledLifetimeManager());
IOCManager.Instance.Container.RegisterType<ISecurityProvider, SecurityProvider>();

Now the question is, how do you get the singleton instance to ever return anything other than the “CanTrade” and “CanPrice”?????

The trick to this is the ContainerControlledLifetimeManager. By holding an instance of this we can use the SetValue(..) method to set a new singleton value.

Here is a full source dump

class Program
{
    static void Main(string[] args)
    {
        ContainerControlledLifetimeManager manager = new ContainerControlledLifetimeManager();

        List privileges = new List();
        privileges.Add("CanTrade");
        privileges.Add("CanPrice");

        SecurityContext sc = new SecurityContext(privileges);

        IOCManager.Instance.Container.RegisterInstance(sc, manager);
        IOCManager.Instance.Container.RegisterType<ISecurityProvider, SecurityProvider>();

        //1st singleton, should show 2 privileges
        Console.WriteLine("1st singleton");
        Console.WriteLine(IOCManager.Instance.Container.Resolve()
                            .Privileges.Aggregate((x, y) => string.Format("-{0} -{1}", x, y)));

        privileges = new List();
        privileges.Add("CanTrade");
        privileges.Add("CanPrice");
        privileges.Add("CanAutoBook");

        sc = new SecurityContext(privileges);
        manager.SetValue(sc);

        //new singleton, should show 3 privileges
        Console.WriteLine("\r\n");
        Console.WriteLine("new singleton");
        Console.Write(IOCManager.Instance.Container.Resolve()
                            .Privileges.Aggregate((x, y) => string.Format("-{0} -{1}", x, y)));
        Console.ReadLine();
    }
}

When this is run you should see the following output:

1st singleton
-CanTrade -CanPrice

new singleton
-CanTrade -CanPrice -CanAutoBook

As always here is a small demo app:

demo project.zip

Advertisements