What is an Auto Mocking Container?
This post started to get a little long, so I won't re-explain the concept.
Joshua Flanagan wrote a nice overview at his Los Techies blog: Auto mocking Explained.
My post is mainly here to describe the Unity version of an automocking container I threw together.
In Jan 2009 I blogged about my initial version of the Unity AutoMocker - Why am I blogging about it again?
I originally wrote the AutoMocker for the Unity container a year ago (Jan 2009, in Silverlight), and finally got around to placing the code up in the moq-contrib project in June of 2009.
I'm writing another post today in hopes to:
- Get some feedback on how this little snippet of code should continue.
- Give a little more how-to/example code
- Describe some updates I made since I originally created it.
Where can I get it?
This is one part where I'd appreciate some feedback.
I have two slightly different versions out there (currently).
I have one version at the ElegantCode repository where I was working on it, and the other I threw up at moq-contrib.
The core of the UnityAutoMockContainer is the same in both places, it's how the tests are separated out that differ.
In the ElegantCode repository it's an all in one self contained single file (that you can copy into your own test project(s)). You can then setup a single test in your own testing framework that runs all internal automocker tests (in case you need to modify it yourself, and don't want to break any existing functionality). EX: test
[Test]
public void Should_run_all_UnityAutoMockContainer_internal_tests()
{
Moq.AutoMocking.SelfTesting.UnityAutoMockContainerFixture.RunAllTests(Console.WriteLine);
}
I kind of like this format as it makes it easy to port between test libraries. Can't say I like having the tests in the same file as the core, but it certainly is not a large chunk of code (so far) so it's relatively small to maintain and definitely easier to manage as a single .cs file than another assembly (which would have to be version dependent on both Unity and Moq).
The moq-contrib is definitely where I think this helper should end up (and it is there). I just happened to break the tests out into the Silverlight test project and the core is alone in a file.
It's current state isn't as easy to copy to a test library (Silverlight/Desktop/Unity 1.2/Unity 2.0) as the one at ElegantCode. What does anyone think? Should I put them all together in one file?
However it ends up (1. all in one file or two (1 test) (1 core)) it will continue to be maintained on the moq-contrib project.
What is the high level API of the container?
It's pretty simple, (currently) there are four methods on the container.
Two for registering items with the container. Say you want to register an already created instance, or say you want to map an interface to a concrete class and not have the container generate mocks automatically for special cases.
And two for pulling items out of the container. Whether you want a instance of T or a Mock
How can I setup my own registrations with the container?
Say I don't want to have the container generate mocks for specific items and I want to supply specific configuration to the UnityContainer.
public UnityAutoMockContainer RegisterInstance<TService>(TService instance)
public UnityAutoMockContainer Register<TService, TImplementation>()
where TImplementation : TService
Note: both of these registration methods return the container itself so you can fluently stack registration. EX:
AutoMockContainer
.Register<IServiceA, ServiceA>()
.Register<IServiceB, ServiceB>();
Let me know: I haven't tested or played around with how this automocking container deals with any container specific xml configuration… So although I don't think you should probably have that in a test assembly (stuff happens). Let me know if there are any issues.
How do I get items out of the container?
First is the Resolve
public T Resolve<T>()
When T is an interface Resolve(new Mock()).Object
When T is a concrete Class, the container should return an instance of T and any of it's dependencies will be satisfied by mocks. (Note that T will not be any sort of mocked instance of T, unless you used the GetMock as described below first)
public Mock GetMock() where T : class
When T is an interface GetMock should return basically (new Mock())
When T is a concrete Class, the container should return a new Mock() and any of it's dependencies will be satisfied by mocks.
How do I use the UnityAutoMockContainer?
It's pretty basic, you first create an instance of the UnityAutoMockContainer, and from there you can ask it for mocks of an (Interface, Class, or Abstract Class).
If you request an instance of a concrete class, or abstract class, the UnityAutoMockContainer will stuff mocks in for any constructor dependencies of your concrete class (if it can). You can then request from the container those same dependencies one at a time and either apply mocking setups or verifications.
NOTE: Anything the container creates will live as a singleton instance in the container. So any other requests from the container will always return the originally created instance. Therefore, each distinct scenario in a test suite should have their own instances of the container.
Below his an example of how you can leverage the container in some tests. Given this base fixture class…
public class FixtureBase
{
private readonly UnityAutoMockContainer _autoMockContainer = new UnityAutoMockContainer();
protected UnityAutoMockContainer AutoMockContainer
{
get { return _autoMockContainer; }
}
[TestFixtureSetUp]
public void SetupContext_ALL()
{
Before_all_tests();
Because();
}
[TestFixtureTearDown]
public void TearDownContext_ALL()
{
After_all_tests();
}
protected virtual void Before_all_tests()
{
}
protected virtual void Because()
{
}
protected virtual void After_all_tests()
{
}
}
If I were given the following system to test.
public interface IServiceA { void RunA(); }
public interface IServiceB { void RunB(); }
public class TestComponent
{
public TestComponent(IServiceA serviceA, IServiceB serviceB)
{
ServiceA = serviceA;
ServiceB = serviceB;
}
public IServiceA ServiceA { get; private set; }
public IServiceB ServiceB { get; private set; }
public void RunAll()
{
if (!HowDidItGo())
return;
ServiceA.RunA();
ServiceB.RunB();
}
public virtual bool HowDidItGo()
{
// some really nasty untestable code
return true;
}
}
The below example demonstrates simply verifying some behavior on the mocked dependencies of the system under test.
[TestFixture]
public class Example__how_to_pull_items_from_the_UnityAutoMockContainer_when_verifying_behavior_after_an_action_was_taken
: FixtureBase
{
private TestComponent _testComponent;
protected override void Before_all_tests()
{
base.Before_all_tests();
_testComponent = AutoMockContainer.Resolve<TestComponent>();
}
protected override void Because()
{
_testComponent.RunAll();
}
[Test]
public void Should_run_ServiceA_RunA()
{
AutoMockContainer
.GetMock<IServiceA>()
.Verify(v => v.RunA(), Times.Once());
}
[Test]
public void Should_run_ServiceB_RunB()
{
AutoMockContainer
.GetMock<IServiceB>()
.Verify(v => v.RunB(), Times.Once());
}
}
Next, you may have noticed that the system under test had a complicated internal method (that may not necessarily be testable). You can use the AutoMocker to create the system under test as a Mock itself, so we can override some of the behavior. Here's how you could quickly do that.
Aside: I'm not saying this is a good practice or aids in good component design, just saying it's possible
[TestFixture]
public class Example__how_to_use_the_UnityAutoMockContainer_to_override_a_method_on_the_SystemUnderTest_to_test_a_certain_behavior
: FixtureBase
{
private TestComponent _testComponent;
protected override void Before_all_tests()
{
base.Before_all_tests();
var mockTestComponent = AutoMockContainer.GetMock<TestComponent>();
mockTestComponent
.Setup(s => s.HowDidItGo())
.Returns(false);
_testComponent = mockTestComponent.Object;
}
protected override void Because()
{
_testComponent.RunAll();
}
[Test]
public void Should_run_ServiceA_RunA()
{
AutoMockContainer
.GetMock<IServiceA>()
.Verify(v => v.RunA(), Times.Never());
}
[Test]
public void Should_run_ServiceB_RunB()
{
AutoMockContainer
.GetMock<IServiceB>()
.Verify(v => v.RunB(), Times.Never());
}
}
It's amazing how much redundant test setup code this little helper has saved me in my tests. I hope others can find some use with this as well.