Search code examples
unit-testingasp.net-mvc-2mockingunity-containerrhino-mocks

Problems with mocking IUnityContainer when testing UnityControllerFactory in MVC project


I am having trouble testing a unity controller factory. I am mcoking out the unity container and asserting that a method was called on it. I am getting invalid cast expection though but cannot really see what is wrong with my code.

Here is the class under test:

public class UnityControllerFactory : IControllerFactory
    {
        private readonly IUnityContainer _container;

        public UnityControllerFactory(IUnityContainer container)
        {
            if (container == null)
            {
                throw new ArgumentNullException("container");
            }

            _container = container;
        }

        public IController CreateController(RequestContext requestContext, string controllerName)
        {
            return _container.Resolve<IController>(controllerName);
        }

        public void ReleaseController(IController controller)
        {
            _container.Teardown(controller);
        }        
    }

and here is the test:

[Test]
        public void CreateControllerCallsResolveOnContainerWithCorrectArgument()
        {
            const string controllerName = "WhateverController";

            var containerMock = MockRepository.GenerateMock<IUnityContainer>();

            var controllerFactory = new UnityControllerFactory(containerMock);

            controllerFactory.CreateController(null, controllerName);

            containerMock.AssertWasCalled(x => x.Resolve<IController>(controllerName));
        }

and here is the error message:

System.InvalidCastException : Unable to cast object of type 'ObjectProxy42336d85f7bb400f9590892348d1d597' to type 'System.Web.Mvc.IController'


Solution

  • The generic Resolve<T>(string) method is an extension method and cannot be mocked. You have two choices here:

    1. Use a non-generic Resolve(Type, string) method or
    2. Wrap IUnityContainer with your own interface so that the generic methods you want to use are interface methods, not extension methods.