Question

The scenario that I currently have is that I am writing a unit test for some code that uses another library of code that uses dependency injection and provides a UnitContainerExtension to bootstrap all the concrete classes required by the library. However in my unit test I want to be able to mock one or two the registered types. Now in theory according to all the post I could see there should be no issue with registering and then re-registering a type. The latter definition / mapping replacing the former.

However this does not seem to work in practice. Now I could just copy the list of type registration from the libraries extension and ommit / change the ones I need to mock. However I thought that this doesn't seem right and maybe I am missing something.

The following is an example of the code (which has been simplified and had the UnitContainerExtension inlined) :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity;
using Moq;

namespace UnityTest
{
    class Program
    {
        private static IFooBar _mockFooBar;

        public static IFooBar MockFooBar
        {
            get
            {   
                return _mockFooBar ?? (_mockFooBar = Mock.Of<IFooBar>(fb => fb.Test(It.IsAny<string>()) == "I am mockery of FooBar!"));
            }
        }

        static void Main(string[] args)
        {
            UnityContainer container = new UnityContainer();

            //Registration of concrete class done inside extension
            container.RegisterType<IFooBar, FooBar>();

            //Re-registering
            container.RegisterType<IFooBar>(new InjectionFactory(uc => MockFooBar));

            //This should resolve to the mocked foobar but doesn't
            Console.WriteLine(container.Resolve<IFooBar>().Test("I am the concrete FooBar!"));
            Console.ReadLine();
        }

        public interface IFooBar
        {
            string Test(string text);
        }

        public class FooBar : IFooBar
        {
            public string Test(string text)
            {
                // Some concrete code
                return text;
            }
        }
    }
}

However the IFooBar type resolves to the concrete FooBar class instead of the Mocked version.

I suspect that calling RegesterType <T> instead of RegisterType<TFrom, TTo> when re-registering might be the issue.

The following is a screen shot of the container at runtime after the second call to RegisterType: enter image description here

Also the same seems to occur using another 'non mocked' class, which is not that surprising as hopefully Unity isn't looking at the type of the mapped to object.

Using the following amended example source:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity;
using Moq;

namespace UnityTest
{
    class Program
    {
        private static IFooBar _mockFooBar;

        public static IFooBar MockFooBar
        {
            get
            {   
                return _mockFooBar ?? (_mockFooBar = Mock.Of<IFooBar>(fb => fb.Test(It.IsAny<string>()) == "I am mockery of FooBar!"));
            }
        }

        static void Main(string[] args)
        {
            UnityContainer container = new UnityContainer();

            //Registration of concrete class done inside extension
            container.RegisterType<IFooBar, FooBar>();

            //Re-registering
            container.RegisterType<IFooBar>(new InjectionFactory(uc => MockFooBar));

            //Re-registering
            container.RegisterType<IFooBar>(new InjectionFactory(uc => new FooBar2()));

            //This should resolve to the mocked foobar but doesn't
            Console.WriteLine(container.Resolve<IFooBar>().Test("I am the original FooBar!"));
            Console.ReadLine();
        }

        public interface IFooBar
        {
            string Test(string text);
        }

        public class FooBar : IFooBar
        {
            public string Test(string text)
            {
                // Some concrete code
                return text;
            }
        }


        public class FooBar2 : IFooBar
        {
            public string Test(string text)
            {
                // Some concrete code
                return "FooBar 2.0";
            }
        }
    }
}

Gives the same results - that is the first registration is used over any of the subsequent ones:

enter image description here

Was it helpful?

Solution

I would say this counts as a bug in Unity but if you already registered the interface to a concrete type, the overwriting registration has to contain a concrete type even though the factory method is used.

In your example:

        container.RegisterType<IFooBar, FooBar>();

        //Re-registering
        container.RegisterType<IFooBar, FooBar>(new InjectionFactory(uc => MockFooBar));

I verified that the type in your overwriting registration could be any concrete type implementing the interface.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top