Test Specific Subclasses vs Partial Mocks

code, tdd comments edit

Sometimes when writing unit tests, you run into the case where you want to override the behavior of a specific method.

Here’s a totally contrived example I just pulled from my head to demonstrate this idea. Any similarity to specific real world scenarios is coincidental ;). Suppose we have this class we want to test.

public class MyController
{
  public void MyAction()
  {
      RenderView("it matches?");
  }

  public virtual void RenderView(string s)
  {
      throw new NotImplementedException("To ensure this method is overridden.");
  }
}

What we have here is a class with a public method MyAction that calls another virtual method, RenderView. We want to test the MyAction method and make sure it calls RenderView properly. But we don’t want the implementation of RenderView to execute because it will throw an exception. Perhaps we plan to implement that later.

Using A Partial Mock

There are two easy ways to test it. One is to create a partial mock using a Mocking framework such as Rhino Mocks.

[TestMethod]
public void DoMethodCallsRenderViewProperly()
{
  MockRepository mocks = new MockRepository();
  MyController fooMock = mocks.PartialMock<MyController>();
  Expect.Call(delegate { fooMock.RenderView("it matches?"); });
  mocks.ReplayAll();

  fooMock.MyAction();
  mocks.VerifyAll();
}

If you’re not familiar with mock framework, what we’ve done here is dynamically create a proxy for our MyController class and we’ve overridden the behavior of the RenderView method by setting an expectation. Basically, the expectation is that the method is called with the string “it matches?”. At the end, we verify that all of our expectations were met.

This is a pretty neat way of testing abstract and non-sealed classes. If a method does something that would break the test, and you don’t want to deal with that, or you don’t care if that method even runs, you can use this technique.

However, there are two problems you might run into this approach. First, VerifyAll doesn’t allow you to specify a message. That is a minor concern, but it’d be nice to supply an assert message there.

Secondly, and more importantly, what if RenderView is protected and not public? You won’t be able to use a partial mock (at least not using Rhino Mocks).

Using a Test-Specific Subclass

One approach is to use a test-specific subclass. I’ve used this test pattern many times before, but didn’t know there was a name for it till my colleague, Chris Tavares of the P&P group (no blog as far as I can tell), told me about the book xUnit Test Patterns: Refactoring Test Code.

In the book, the author categorizes various useful test techniques into groups of test patterns. The Test-Specific Subclass pattern addresses the situation described in this post. So looking at the above code, but assuming that RenderView is protected, we can still test it by doing the following.

[TestMethod]
public void DoMethodCallsRenderViewProperly()
{
  FooTestDouble fooDouble = new FooTestDouble();
  fooDouble.MyAction();
  Assert.AreEqual("it matches?", fooDouble.ReceivedArgument, "Did render the right view.");
}

private class FooTestDouble : MyController
{
  public string ReceivedArgument { get; private set; }

  protected override void RenderView(string s)
  {
      this.ReceivedArgument = s;
  }
}

All we did was write a class specific to this test called FooTestDouble. In that class we override the protected RenderView method and set a property with the passed in argument. Then in our test, we can simply check that the argument matches our expectation (and we get a human friendly assert message to boot).

Is this a valid test pattern?

Interestingly enough, I have shown this technique to some developers who told me it made them feel dirty (I’m not naming names). They didn’t feel this was a valid way to write a unit test. One complaint is that one shouldn’t have to inherit from a class in order to test that class.

So far, none of these complaints have provided empirical reasons behind this feeling that it is wrong. One complaint I’ve heard is that we are not testing the class, we are testing a derived class.

Sure, we’re technically testing a subclass and not the class itself, but we are in control of the subclass. We know that the behavior of the subclass is exactly the same except for what we chose to override.

Not only that, the same argument could be applied to using a partial mock. After all, what is the mocking example (which many feel is more appropriate) doing but implicitly generating a class that inherits from the class being tested whereas this pattern explicitly inherits from the class.

My own feeling on this is - I want to choose the technique that involves less code and is more understandable for any given situation. In some cases, using a mock framework does this. For example, in the first case when RenderView is public, I like having my test fully self-contained. But in the second case, RenderView is protected, I think the test-specific subclass is perfectly valid. The test-specific subclass is also great for those who are not familiar with a mock framework.

While some guidelines around TDD and unit testing are designed to produce better tests (for example, the Red Green approach and trying not to touch external resources such as the database) and better design, I don’t like to subscribe to arbitrary rules that only make writing tests harder and don’t seem to provide any measurable benefit based on some vague feelingof dirtiness.

Tags: TDD , Unit Testing , Test Specific Subclass

Comments