Tech and Media Labs
This site uses cookies to improve the user experience.




Subclass Mock Objects

Jakob Jenkov
Last update: 2014-08-08

Subclass mock objects is a mock object that is created by subclassing the class you want to test, and overriding some of its methods. Let's look at a simple class:

public class MyUnit {

  protected MyDependency dependency = null;

  public MyUnit(MyDependency dep) {
    this.dependency = dep;
  }

  public void doTheThing(String param) {

    if("one".equals(param)) {
      dependency.callOne();
    } else {
      dependency.callTwo();
    }
  }
}

The class MyUnit is the class I am trying to unit test. In this unit test, I want to check if the MyUnit class calls the MyDependency class correctly. There are 3 ways to do this:

  1. Create a Mock implementation of the MyDependency class, using a proxy object
  2. Create a subclass mock of the MyDependency class, and override the callOne() and callTwo() methods
  3. Create a subclass of the MyUnit class itself, and use that during testing.

In this text I will show you how to do nr. 3. From that method it should be fairly easy to figure out how to do number 2, in case you want that.

Using method nr. 3 requires the following steps:

  1. Encapsulate calls to MyDependency inside MyUnit
  2. Create a subclass of MyUnit
  3. Override the MyDependency call encapsualation methods.

I will show you how to perform these three steps, throughout the rest of this text.

Step 1: Encapsulate calls to MyDepedency

The first thing to do is to refactory the MyUnit class, so that all calls to the MyDependency class are encapsulated in their own methods. Here is how that looks:

public class MyUnit {

  protected MyDependency dependency = null;

  public MyUnit(MyDependency dep) {
    this.dependency = dep;
  }

  public void doTheThing(String param) {

    if("one".equals(param)) {
      callOne();
    } else {
      callTwo();
    }
  }

  protected void callOne() {
      dependency.callOne();
  }

  protected void callTwo() {
      dependency.callTwo();
  }
}

Notice how the two calls to MyDependency.callOne() and MyDependency.callTwo() are now encapsulated in two protected methods, callOne() and callTwo().

We are now ready to create the MyUnit subclass.

Step 2: Create a Subclass Mock of MyUnit

The second step is to create a subclass mock of the MyUnit class. Here it is:

public MyUnitMock extends MyUnit {

  protected boolean callOneCalled = false;
  protected boolean callTwoCalled = false;

  @Override
  protected void callOne() {
    this.callOneCalled = true;
    super.callOne();
  }

  @Override
  protected void callTwo() {
    this.callTwoCalled = true;
    super.callTwo();
  }

}

Notice how the two overridden methods records if they are called or not, by setting a boolean to true.

The next step is to use the MyUnitMock in your unit test.

Step 3: Using the MyUnitMock Class in Your Unit Tests

Here is a unit test method that uses the MyUnitMock class:


@Test
public void test() {
   MyUnitMock myUnitMock = new MyUnitMock();

   myUnitMock.doTheThing("one");

   assertTrue (myUnitMock.callOneCalled);
   assertFalse(myUnitMock.callTwoCalled);

   //reset mock before next call
   myUnitMock.callOneCalled = false;

   myUnitMock.doTheThing("two");

   assertFalse(myUnitMock.callOneCalled);
   assertTrue (myUnitMock.callTwoCalled);
}

First an instance of the MyUnitMock class is created. Second, the doTheThing() method is called. Third, assertions are made about whether the callOne() and callTwo() method were invoked.

Summary

As you can see, it is possible to test almost all of a class by using subclass mocks, as described above. There are, however, situations where it works better to use a completely separate mock dependency object with the original class instead. Exactly when, depends on the concrete application.

Just keep in mind, that the above is just a suggestion - one possible method. Use it when it make sense, and don't use it when it doesn't make sense. Use your judgement!

Jakob Jenkov




Copyright  Jenkov Aps
Close TOC