Unit Tests: Mocking a base class method

This example talks about testing a method in a subclass that calls a base class method. Calling the base class method has side effects (e.g relies on a database / httpcontext, or in this example calls console.writeline), so need to be mocked out in order to allow testing of the method in the subclass.

To allow this to be mocked when called from tests, an additional constructor can be create (i.e. as per standard Dependency Injection), that passes in a new implementation of the method in the base class (via the Action / Func keyword). A delegate exists in the subclass that can then be called via an overload of the mocked method (as long as that method was virtual in the base).

Note that when not testing, the normal constructor is called – this just assigns the base implementation of the method to the delegate, thus giving normal behaviour. The code below demonstrates:

The base class contains a method that needs to be mocked as it has side effects:

public abstract class BaseClass
{
    protected virtual void DoSomethingUsingContext(string message)
    {
        Console.WriteLine(“Doing something against the context – e.g. httpcontext: {0}”, message);
    }

    public abstract void DoSomethingImportant();       
}

We want to test “DoSomethingImportant” on the deriving class shown below. This requires a dependency injection constructor to allow  “DoSomethingUsingContext” to be mocked. Note that “Action<string>” defines a delegate with the same signature as “DoSomethingUsingContext”.

public class ConcreteClass : BaseClass
{
    Action<string> doSomethingUsingContext;

    public ConcreteClass(Action<string> doSomethingUsingContextImplementation)
    {
        this.doSomethingUsingContext = doSomethingUsingContextImplementation;
    }

    public ConcreteClass()
    {
        this.doSomethingUsingContext = base.DoSomethingUsingContext;
    }

    protected override void DoSomethingUsingContext(string message)
    {
        this.doSomethingUsingContext(message);
    }

    public override void DoSomethingImportant()
    {
        // Do something important here

        this.DoSomethingUsingContext(“A message about something”);
    }
}

Finally, we can inject a mock implementation of “DoSomethingUsingContext” from our unit test (note in this example we write to debug listeners instead of the console – when debugging you can see output in the output window of visual studio).

[TestMethod]
public void TestMethod1()
{
    bool doSomethingUsingContextWasCalled = false;
    Action<string> testImplementation = (x) => { Debug.WriteLine(x); doSomethingUsingContextWasCalled = true; };

    ConcreteClass myClass = new ConcreteClass(testImplementation);
    myClass.DoSomethingImportant();

    Assert.IsTrue(doSomethingUsingContextWasCalled);
}

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>