Auto-Mocking Unity Container Extension

Using a container for unit testing is a good way to insulate your tests from changes in object construction. Typically my first test will be something pretty boring just to get the process started. A few tests later, the real behavior comes out along with new dependencies. Rather than having to go back and add the dependencies to all the tests I’ve already written, I like to use a container to build up the object I’m testing.

To streamline this process, I thought it would be handy to use a container extension to auto generate mocks for any required interface that wasn’t explicitly registered. The best way I can explain this is with code, so here it is:

[SetUp]
public void SetUp()
{
    container = new UnityContainer()
        .AddNewExtension<AutoMockingContainerExtension>();
}
 
[Test]
public void Should_be_really_easy_to_test()
{
    container
        .RegisterMock<IDependencyThatNeedsExplicitMocking>()
        .Setup(d => d.MyMethod(It.IsAny<int>()))
        .Returns("I want to specify the return value");
 
    var service = container.Resolve<ServiceWithThreeDependencies>();
    var result = service.DoSomething();
 
    Assert.That(result, Is.EqualTo("I didn't have to mock the other 2 dependencies!"));
}
 

It really reduces the noise level in tests and lets you focus on the interesting parts of your application. Here’s the code for the container extension:

luigi

public class AutoMockingContainerExtension : UnityContainerExtension
{
    protected override void Initialize()
    {
        var strategy = new AutoMockingBuilderStrategy(Container);
 
        Context.Strategies.Add(strategy, UnityBuildStage.PreCreation);
    }
 
    class AutoMockingBuilderStrategy : BuilderStrategy
    {
        private readonly IUnityContainer container;
 
        public AutoMockingBuilderStrategy(IUnityContainer container)
        {
            this.container = container;
        }
 
        public override void PreBuildUp(IBuilderContext context)
        {
            var key = context.OriginalBuildKey;
 
            if (key.Type.IsInterface && !container.IsRegistered(key.Type))
            {
                context.Existing = CreateDynamicMock(key.Type);
            }
        }
 
        private static object CreateDynamicMock(Type type)
        {
            var genericMockType = typeof(Mock<>).MakeGenericType(type);
            var mock = (Mock)Activator.CreateInstance(genericMockType);
            return mock.Object;
        }
    }
}
 

In case you’re wondering about container.RegisterMock<>, it’s just extension method that you can read about here.

14 Comments  »

  1. Hi Michael,

    It is a great approach! My team is having whole lot of trouble with hundreds of noisy unit test and writting an extension for UnityContainer just nevet come to out mind :)

  2. Omar says:

    Great post. The details of the RegisterMock(..) method are not clear. Can you please include the code to RegisterMock or elaborate more on how this method makes the magic happen.

  3. Omar says:

    Disregard previous post – got the technique. Good Kung-Fu.

  4. Paolo says:

    Really useful!
    But I can’t find the RegisteMock() method code.
    Omar where did you find it? Or Michael can you post the code?
    Thanks!
    Paolo

  5. Michael Valenty says:

    Thanks Paolo! I posted the code here: Moq Extension Methods for Unity

  6. Jay says:

    Hi,

    Great post!. Can you pls post the working code of this unity extension coz I tried but I cannot make it work now. ^^

    Thanks

  7. Michael Valenty says:

    Thanks Jay, I added a link to download the source at the end of the article.

  8. Jay says:

    Hi Michael,

    Thank you very much for the source, really appreciate the effort. :)

    I’ll play around with the source then I’ll try to provide some feedback.

    Thanks again.

  9. Paul says:

    Hi Michael

    I’m a bit confused about this blog post and the one it links to. They seem to jump between Moq and Rhino Mocks and the source code include references to both Moq and Rhino Mocks?

    Thanks

  10. Michael Valenty says:

    Paul,

    I know it’s weird that both mocking frameworks are referenced, but there is a reason. I prefer to use Moq in my unit tests because I like the fluent API. The problem is that Moq does not have an API to generate a mock from a runtime type, only compile-time types using generics. For example, with Moq I cannot do this:

    var mock = new Mock(theTypeToMock);

    RhinoMocks however, does support this syntax so I use it under the hood in one spot. For my day-to-day unit tests, it’s all Moq. I wrote this stuff about a year ago and it’s possible that Moq now supports this in which case you could get rid of the dependency on RhinoMocks.

  11. Suiden says:

    Hi Michael,

    You should be able to get rid of RhinoMocks this way:

    var genericMockType = typeof(Mock<>).MakeGenericType(key.Type);
    var mock = (Mock)Activator.CreateInstance(genericMockType);
    context.Existing = mock.Object;

  12. Michael Valenty says:

    Great idea, thanks! I updated code with your change and also took advantage of the new Unity 2.0 IsRegistered method.

  13. Kevin says:

    Great post. Very useful and time saving.

  14. George Polevoy says:

    Would be great to have it work with MockRepository

    private Mock CreateDynamicMock(Type type)
    {
    return _mockRepository.Create(type);
    }


    public static class MockRepositoryExtensions
    {
    ///
    /// Placeholder interface to make a strong reference to a generic method call
    ///
    private interface IPlaceholderInterface
    {
    }
    public static Mock Create(this MockRepository mockRepository, Type type)
    {
    Expression<Func<MockRepository, Mock>> l = mr => mr.Create();
    var mc = (MethodCallExpression)(l.Body);
    var genericCreate = mc.Method.GetGenericMethodDefinition();
    var instantiatedCreate = genericCreate.MakeGenericMethod(type);
    return (Mock)instantiatedCreate.Invoke(mockRepository, null);
    }
    }

Trackbacks/Pingbacks

    1. Moq Extension Methods for Unity | Agile at Work
    2. proxy
    3. sheffield builder

    RSS feed for comments on this post, TrackBack URI

    Leave a Comment