Recently I have really gotten into Test Driven Development (TDD). My first real try at TDD was for a library that I have yet to complete for integrating spriter animations into FlatRedBall. Now I am working on something work related, so I can’t give any specific details as it is proprietary information. I can, however, come up with some contrived examples that may be beneficial to the community regarding Mocking.

There are several different mocking frameworks out there, and I started using Moq first, but I have changed to using Telerik JustMock because it has a less verbose syntax. I may post a “differences between Moq and JustMock” some day, but others have already covered that on the web, so it really isn’t necessary.

I also find great value in dependency injection, so IoC containers are invaluable in my production code; however, something I have also recently learned is that they can be just as invaluable in a unit test. Implementing the dependency injection pattern enables techniques such as inversion of control (IoC), which allow specifying concrete dependencies at runtime for abstract dependencies. That is to say, if class A relies on interface I, and B implements I, class C associates A with B at runtime without either class knowing of the other. Example:

public class Foo
{
    private IWorker _iworker;
    public Foo(IWorker iworker)
    {
        _iworker = iworker;
    }

    public string DoWork()
    {
        return _iworker.DoWork();
    }
}

public interface IWorker
{
    string DoWork();
}

public class Bar : IWorker
{
    public string DoWork()
    {
        return "Bar";
    }
}

We have two classes. Foo which has a dependency on an abstraction (interface IWorker). You can see that Foo doesn’t have any reference to class Bar in this example, and the reverse is true. Bar doesn’t know anything about Foo.

One might use this class in the following manner:

// Manually injecting the dependency through a constructor
var foo = new Foo(new Bar());

// or by Automatically injecting the dependency by setting up an IoC container
var container = new UnityContainer();
container.RegisterType<IWorker, Bar>();

// Typically the below step is done by a dependency resolver which depends on a
// container of some sort, but for a concise example:
Foo foo = container.Resolve<Foo>();

I’ll let the comments explain the code. Suffice it to say that the second pattern is much nicer, because a third class is responsible for coupling all of your dependencies. In MVC, this is typically a BootStrapper static class, but it can be anything that sets the MVC configuration’s global DependencyResolver object.

Why should you use this pattern in your class design? Unit tests! Unit tests! Unit tests!

Example:

[TestMethod]
public void a_dowork_returns_dowork_from_IWorker()
{
    // Arrange
    var container = new MockingContainer(); 
    container.Arrange(i => i.DoWork()).Returns("test");

    // Act 
    Foo foo = container.Instance;
    var result = foo.DoWork();

    // Assert
    Assert.AreEqual("test", result);
}

Mind blown? There’s a lot going on here, but essentially:

Arrange:
The unit test takes advantage of the dependency injection pattern and injects a proxy implementation of the IWorker interface into the Foo object it maintains inside the MockingContainer. The call to Arrange is saying that this proxy object should return “test” for any calls to its DoWork function. So we have an object that implements IWorker (it has nothing to do with class Bar), and we inject that into the instance of Foo automatically with the container.

Act:
We then call DoWork on the instance of Foo that the container provides us (which has the dependency injected already)

Assert:
We assert that the result returned from foo.DoWork() matches what the proxy DoWork was returning.

This is a simple contrived example, but it illustrates how IoC containers work in tandem with mocking very well. I hope someone finds this useful!

One thought on “Unit testing with mocks

  1. Pingback: Test driven development (TDD) should drive your class design (Part 2 of 2): The right way | Geek Powers

Leave a Reply

Your email address will not be published. Required fields are marked *