Wednesday, April 7, 2010

Mole Instances and Moling Instance Methods

So far, we’ve seen how to mole static methods and how to stub interfaces and abstract and virtual methods. What’s left? Moling instance methods that can’t be overridden by following the rules. Moles aren’t just for static methods – you can also create mole instances that override methods that normally can’t be overridden and swap them in for the real thing.

Here’s the context for today’s post:
public class Example
{
    MyDependency m_dependency;

    public Example()
        : this(new MyDependency(10))
    {
    }

    public Example(MyDependency dependency)
    {
        m_dependency = dependency;
    }

    public string Execute()
    {
        return "Dependency string is: " + m_dependency.MyDependencyMethod();
    }
}

public class MyDependency
{
    int m_dependencyInt;

    public MyDependency(int myInt)
    {
        m_dependencyInt = myInt;
    }

    public string MyDependencyMethod()
    {
        return "MyInt times 2 = " + m_dependencyInt * 2;
    }
}
Here we’ve got a class, Example, that takes a dependency of a specific type into its constructor. The type specified isn’t an interface, but a concrete, non-abstract type. It’s not sealed (although it could be for purposes of this example), but it doesn’t have any virtual methods, so it can’t be replaced with a stub. Something like this could happen in practice when a developer gets a bright idea about constructor dependency injection, but never ends up finding a need to abstract the type of the dependency out to an interface (in real life, what’s more likely is that the developer would just new up an instance of the dependency right within the class – I’ll get to that soon). We’d like to test Example.Execute isolated from its dependencies, so we create a mole instance in our test and hand that in to the Example constructor instead.
[TestMethod()]
[HostType("Moles")]
public void ExecuteTest()
{
    MMyDependency mole = new MMyDependency
    {
        MyDependencyMethod = () => "Moled method!";
    };
    Example target = new Example(mole);
    string actual = target.Execute();
}
I gave MyDependency a little bit of state to give you something to think about – notice that the moled version of MyDependency has no concept of state. When you mole a class, it loses its “classiness” and becomes nothing more than a collection of methods. If you want to give a mole state, you can store that state within variables inside the test method, and then refer to those variables from within your lambda expressions. This works because of closures (warning: that link goes to a piece written by Jon Skeet, meaning that if you read it and keep exploring his other stuff, you will lose most of your day), one of the most beautiful ideas in all of programmingdom. However, think hard before doing this – it’s likely to be way more than you actually need for purposes of your test. One thing you can do, if you want to put the work in, is use state to make a mole or a stub into a mock, with expectations about what methods will be called and with what parameters.

What if your class under test doesn’t let you inject the dependency? Check the next post for information about how to mole constructors, use a mole type to affect all calls to a given instance method on all instances, and a little bit of insight as to how moles work.

No comments: