Unity Automocking

Mar 11, 2013 at 8:47 PM
Edited Mar 11, 2013 at 8:48 PM
Hi,

I'm trying to use Unity along with Moq in order to have an Automocking container to make my tests more maintainable. Giving these interfaces/classes:
public interface IDependency
{
    int Numero { get; }
}

public class Dependency : IDependency
{
    public int Numero { get { return 1; } }
}

public interface IOwner
{
    int Number();
}

public class Owner : IOwner
{
    private readonly IDependency _dependency;

    public Owner(IDependency dependency)
    {
        _dependency = dependency;
    }

    public int Number()
    {
        return _dependency.Number;
    }
}
And this test example:
public void TestAutomockContainer()
{
    IUnityContainer container = new UnityContainer();

    container.AddExtension(new AutoMoqExtension());
    container.RegisterType<IDependency, Dependency>(new ContainerControlledLifetimeManager());
    container.RegisterType<IOwner, Owner>(new ContainerControlledLifetimeManager());

    container.Resolve<Mock<IDependency>>()
        .Setup(r => r.Numero)
        .Returns(12);

    var sut = container.Resolve<IOwner>();
    Assert.AreEqual(12, sut.Numero());   
}
Unity does a great job in creating the needed instances and making my tests constructor changes proof. But, there are situations where I need to setup a dependency (stub/mock) before calling sut in order to make sure that what I expected is actually what happened. That's the time Moq would join the party and give me the same instance (passed in the constructor) to be set up (that's the reason why I registered the types as ContainerControlledLifetimeManager).

Here is what I could come up with in order to try to solve that issue:
public class AutoMoqExtension : UnityContainerExtension
{
    protected override void Initialize()
    {
        var autoMoqBuilderPolicy = new AutoMoqBuilderPolicy();

        Context.Policies.Set(typeof(IBuildPlanPolicy),
            autoMoqBuilderPolicy,
            new NamedTypeBuildKey(typeof(Mock<>)));
    }
}
And...
public class AutoMoqBuilderPolicy : IBuildPlanPolicy
{
    public void BuildUp(IBuilderContext context)
    {
        if (context.Existing == null)
        {
            var currentContainer = context.NewBuildUp<IUnityContainer>();
            var buildKey = context.BuildKey;

            context.Existing = CreateResolver(currentContainer, buildKey.Type);
        }
    }

    private object CreateResolver(IUnityContainer currentContainer, Type typeToBuild)
    {
        var mockType = typeof(Mock<>).MakeGenericType(typeToBuild.GetGenericArguments()[0]);
        return ((Mock)currentContainer.Resolve(mockType)).Object;
    }
}
I tried several variations of this code but none of them worked. Basically when the execution gets to this line:
return ((Mock)currentContainer.Resolve(mockType)).Object;
The build police gets executed again instead of giving me back the proper instance.

Is it possible to achieve that using Unity or am I pushing it to far?

Thanks
Mar 12, 2013 at 2:36 AM
You are getting a StackOverflowException because you are attempting to resolve the type during the build chain. The call to resolve kicks off another build chain, etc.

What you will have to do is create the object without the container. You might want to take a look at UnityAutoMoq since it seems to be in line with what you are trying to do.

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to