Design for testability – Auto Mocking Container (AMC) – Part 9

On my quest to design for testability, I’ve already covered:

My today’s post would be covering AutoMockingContainer (AMC) in both “standard” and “service locator based” versions

What is auto mocking container (AMC)?

I’ll use the example from original Elutian blog post (where the concept of AMC is first mentioned) where the test setup code looks like this:

[SetUp]
public void Setup()
{
  _service1 = _mocks.CreateMock<IService1>();
  _service2 = _mocks.CreateMock<IService2>();
  _service3 = _mocks.CreateMock<IService3>();
  _serviceWeAreTesting =
       new DefaultServiceWeAreTesting
            (_service1, _service2, _service3);
}

This example applies transparent dependency injection style described in previous post with a class expose a constructor accepting many interface parameters "(“services”) to which class functionality is dependable on.  On first look, there is nothing wrong with the example above but once you would be doing serious testing you would probably find out two things:

  • (PIA) during test creation you would probably feel that it is too much “plumbing” code to be done to support testing
  • (REAL PIA) long after once the tests would be done someone would add to that class constructor another parameter (“service4”) and each one of the tests you created would start crashing although probably the functionality you were testing is not relying on _service4 at all.

To tackle those two issues, smart people at Elutian combined Rhino mocks and Windsor container to tackle those problems.

Using AMC the same test setup code would look like this:

[SetUp]
public void Setup()
{
  _mocks = new MockRepository();
  _container = new AutoMockingContainer(_mocks);
  _service = _container.Create&lt;DefaultServiceWeAreTesting&gt;();
} 


As you can see, in case of AMC we construct AutoMockingContainer with MockRepository instance thrown as parameter.

That allow’s us to replace explicit mock creation and concrete constructor invocation with AMC container Create method which accept as generic type parameter the type we plan to test.

Windsor would then find out the constructor which needs to be used and for each one of the service interfaces (if they are not in container) would create a dynamic mock class implementing given interface (thanks to Rhino mocks).

so now when we have this initialized writing the test is much simpler and looks like this (taken from the same Elutian blog post)

[Test]
public void DoWork_Always_AsksOtherServices()
{
  using (_mocks.Unordered())
  {
    _container.Get&lt;Service1&gt;().DoWork();
    _container.Get&lt;Service2&gt;().DoWork();
    _container.Get&lt;Service3&gt;().DoWork();
  }
  _mocks.ReplayAll();
  _service.DoWork();
  _mocks.VerifyAll();
}

As you can see, we are not explicitly constructing service class and registering services to container. AMC container already created instance and add components to container in setup method so all we need to do in test is to use them.

Obviously:

This is much shorter to be written –> issue #1 is solved.

Even if we would add additional  constructor parameter the AMC would recognize that IService4 was added and it would add its mock to container effectively preserving the test not depending on IService4 runable  –> issue # 2 resolved

(To get AMC source code which you can compile on your box and use, click here)

Auto mocking container and Unity

As I mentioned above, the AMC solution given above is for Castle Windsor IoC framework and my IoC framework lately become Microsoft Unity (due to the reasons stated in DFT Unity post), so I did little search for Unity AMC and found out that Roy Osherove implemented it already.

Roy provided in that blog post example how test looks:

[Test]
public void MockTwoDependenciesForAConstructor()
{
	MockRepository mocks = new MockRepository();
	AutoMockingUnityContainer container =
        	new AutoMockingUnityContainer(mocks);

	container.WillReturnAStubFor<ILogger>();
        container.WillReturnAStubFor<IEmailer>();

	using (mocks.Record())
	{
		//Tell our mock to return true when this method is called
        	container.Resolve<ILogger>().IsLogFileFull();
                LastCall.Return(true);
	}

	//runner class takes both of these mocks in its constructor
        Runner runner = container.Resolve<Runner>();
        Assert.IsNotNull(runner);
}

Well, although his implementation is VERY cool way of “create mock and inject it to container”  it is not (at least how I get it) the AMC like the one Elutian guys did because I am still expected to define stubs and inject them to container explicitly (although on short&easy way)  (issue #1 still exist).

But, #2 (more important one) is handled with this because test code not depending on the additional dependency wouldn’t crash.

So, all in one, if you do IoC with Unity go to mentioned Roy blog post and copy paste the Unity AMC source code for your own usage.

Auto mocking container – my way

Well, as I presented in previous post, currently the way I am writing and testing my code is that I declare internal constructor accepting the dependencies and perform mock injection without using of any IoC framework.

But, even for me issues #1 and #2 are not a big problem (I don’t mind declaring mocks and I WANT my test to crash when tested lass change so I have to check out the tests), I can imagine that for some of people this wouldn’t be the case. For them, testing on the simplest possible way with #1 and #2 resolved would be “have to” requirement.

The good news here is that there is solution for this almost “out of the box” thanks to the design decisions I made in previous posts:

  • I would have Facade component (ServiceLocator) encapsulating concrete IoC framework usage
  • Default constructor performs “poor man dependency injection” using the ServiceLocator

If we think about what the problem really is AMC tries to solve we would come up with something like this:

“When IoC container is asked to retrieve a type implementing some interface and that mapping is not defined, return a mocked instance of the interface.”

And that is exactly what I would do…

Modifying ServiceLocator

ServiceLocator class is going to support testing mode when instead of IoC container exception throwing (for cases of no type can be retrieved from IoC container for a given interface) ServiceLocator would create a new mocked instance. Something like this:

using System;
using Microsoft.Practices.Unity;
using Rhino.Mocks;

namespace Facade
{
    public static class ServiceLocator
    {
        private static readonly MockRepository _mockery
            = new MockRepository();
        private static readonly UnityContainer _unityContainer
            = new UnityContainer();

        public static bool TestMode { get; set; }

        public static void InjectStub(I instance)
        {
            _unityContainer.RegisterInstance(instance
                , new ContainerControlledLifetimeManager());
        }

        public static T Retrieve<T>;()
        {
            try
            {
                return _unityContainer.Resolve<T>();
            }
            catch (ResolutionFailedException e)
            {
                if (TestMode)
                {
                    return _mockery.DynamicMock<T>();
                }
                throw new InvalidOperationException(“Can't resolve dependency.”;, e);
            }
        }
    }
}

As you can see service locator now has dependency to Rhino mocks (MockReporsitory class) which is ok IMHO. There is also TestMode new boolean property which represents the way to switch ServiceLocator from production to test mode. Retrieve method now puts IoC Resolve method call inside of try block. In catch block there is conditionalization based  on TestMode value: in case ServiceLocator is in test mode mocked instance is returned and in case ServiceLocator is in production mode Unity exception is been bubbled up.

And that would be all what we need to do to support custom AMC.

Writing tests using custom AMC

Now when we have the AMC container done, let’s check out how the test from last blog post would look like now with custom AMC used.

Let add first additional dependency to UserManager constructor so we would have the right use case for AMC (original constructor had only one IUserProvider in which case AMC usage doesn’t have sense)

So the UserManager class would look after that modification something like this

    public class UserManager : IUserManager
    {
        private readonly IUserProvider _userProvider;
        private readonly ISomeOtherDependency _someOtherDependency;

        public UserManager()
            : this(ServiceLocator.Retrieve<IUserProvider>(),
                   ServiceLocator.Retrieve<ISomeDependency>()) { }

        internal UserManager(IUserProvider userProvider, ISomeDependency someDependency)
        {
            _userProvider = userProvider;
            _someOtherDependency = someOtherDependency;
        }

        #region IUserManager Members
        public int NumberOfUsersActiveInLast10Days(string userName)
        {
            var userCollection = _userProvider.GetUserCollection();
            var result = 0;
            foreach (var user in userCollection)
            {
                if (user.Name.StartsWith(userName)
                    && user.LastActivity > DateTime.Now.AddDays(-10))
                    result++;
            }
            return result;
        }
        #endregion
    }

Note that constructor now have additional parameter of ISomeDependency type.

The test similar to the one from last post but this time using the AMC would look like this:

    [TestFixture]
    public class UserManagerTest
    {
        private MockRepository mockRepository;

        [SetUp]
        public void Test_Init()
        {
            mockRepository=new MockRepository();
            ServiceLocator.TestMode = true;
        }

        [Test]
        public void GetActiveUsers_TestCaseOfZeroUsers_WouldReturnEmptyCollection()
        {
            IUserProvider userProvider =
                mockRepository.DynamicMock<IUserProvider>();
            ServiceLocator.InjectStub(userProvider);

            using (mockRepository.Record())
            {
                Expect.Call(userProvider.GetUserCollection())
                    .Return(new List<User>());
            }
            using (mockRepository.Playback())
            {
                // using public ctor(NO EXPOSED PARAMETERS)
                var userManager = new UserManager();
                int numberOfUsers= userManager.NumberOfUsersActiveInLast10Days(“X”);
                Assert.IsTrue(numberOfUsers == 0);
            }
        }
    }

Couple of key moments here:

  • In test init method I switch ServiceLocator to “test mode” –> command him to return mocks for all types not stored in IoC container in the moment of their retrieval request
  • In test method I am explicitly adding to ServiceLocator ONLY instance of IUSerProvider (which is related to this test) .
  • ISomeDependency parameter is not mentioned anywhere in the test (solution to #1)
  • I am using the default constructor. That is giving me the solution to #2 which looks very strange on first sight but once one would realize that behind that default constructor is ServiceLocator based poor man dependency injection things get clearer.

Again, I am aware that this approach to AMC is probably unique (I didn’t saw anything like this on the web) but I just choose to do the AMC through component design and not by some AMC framework (although that is perfectly fine choice with me too)

Conclusion

Although I like to keep things in my own hands as much as possible, I see a lot of value coming from AMC usage in writing tests for people who like the AMC idea.

For people not sure “which pill to take” there comes the list of pros and cons I found on the web (here and here)

Pros

  1. Can be easier to maintain and write tests/Can lead to easier test maintainability.
  2. Allows easier focus on testing interaction.
  3. Automatic testing the services construction via the IoC container.

Cons

  1. Speed/performance?
  2. It could make the test a little less readable in terms of understanding what gets injected and what the actual dependencies are.

 

What’s next

My DFT blog post series stops here because I am getting fed up writing about unit testing and not having fun doing it is a sign for switching gears 🙂

I have recently some real world experience on MVP design pattern appliance in real world scenarios so I plan to write couple of posts describing my thoughts on how to solve common problems most of the people face doing MVP (tackling complexity, communication controlpage, need for HttpContext in presenter, composite UI communication, Front controller routing  etc) so in case you are doing WebForm classic ASP NET development and you care about testing your UI stay tuned

Useful links for AutoMockingContainer

http://blog.eleutian.com/2007/08/05/UsingTheAutoMockingContainer.aspx

http://www.ayende.com/Blog/archive/2007/06/08/The-Auto-Mocking-Container.aspx

http://blog.eleutian.com/2007/02/23/TestsAutoMockingIoCContainer.aspx

AMC custom implementation source code can be found here

 

Advertisements

Posted on June 9, 2008, in Uncategorized. Bookmark the permalink. 1 Comment.

  1. This has been a great series! I wonder however why Spring was not also shown in this series?
    Thanks again!
    Dave

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: