Test Doubles: creating a Dummy Object using a mocking framework

In this series of posts about Test Doubles we’ll look at five examples. In the previous post we looked the manual creation of a dummy object. The conclusion was that the manual approach is functional but laborious. This post focuses on the creation of a dummy object using a mocking framework. We’ll look at Mockito and JMockit. There are many other frameworks out there that can pretty much do the same thing. But for brevity’s sake we’ll skip those. If you want, you can clone / download the examples used in this post on github.

The problem we’re looking at
Just to reiterate, we test adding a line item on a CheckInSheet for a pawnshop. But we have some setup to do.

  • In order to instantiate the check-in sheet we need a Pawner.
  • The Pawner requires us to make an Address.
  • The Address needs a City.
  • The City cannot be made without a Province.

A test without a dummy object would look like this.

@Test
public void check_in_sheet_should_add_line_item() {
  final int NUMBER_OF_ITEMS = 1;
  Asset asset = new Asset(getUniqueText());      
    
  // four lines of unnecessary setup  
  Province province = new Province("Zuid Holland", "ZH");      
  City city = new City("The Hague", province);
  Address address = new Address("Spui 138", city, "2525 TT");
  Pawner pawner = new Pawner(getUniqueText(), getUniqueText(), address);
    
  CheckInSheet checkInSheet = new CheckInSheet(pawner);     

  checkInSheet.add(asset);

  List lineItems = checkInSheet.getLineItems();
  assertEquals("number of items on the check in sheet", NUMBER_OF_ITEMS, lineItems.size());
  assertEquals("the right item on the check in sheet", asset, lineItems.get(0));
}

So many lines just to create a Pawner that isn’t even used by the SUT in this test! We can delete half of the test if we use a dummy object. A dummy object is defined as follows.

A placeholder object that is passed to the SUT as an argument (or an attribute of an argument) but is never actually used

Improving the test with Mockito
It takes very little work to improve our test. We’ll use Mockito to do two things.

  1. Make a dummy object for Pawner
  2. Ensure that the SUT does not interact with the dummy object

The test now looks like this.

Pawner dummyPawner = mock(Pawner.class);

@Test
public void check_in_sheet_should_add_line_item() {
  final int NUMBER_OF_ITEMS = 1;
  Asset asset = new Asset("Dummy Asset Name");      
  CheckInSheet checkInSheet = new CheckInSheet(dummyPawner);     

  checkInSheet.add(asset);

  List<Asset> lineItems = checkInSheet.getLineItems();
  assertEquals("number of items on the check in sheet", NUMBER_OF_ITEMS, lineItems.size());
  assertEquals("the right item on the check in sheet", asset, lineItems.get(0));
    
  verifyZeroInteractions(dummyPawner);
}

We create a dummy object with the statement Pawner dummyPawner = mock(Pawner.class); (see JavaDoc mock ) and use it to instantiate the CheckInSheet. The last statement verifyZeroInteractions(dummyPawner); (see JavaDoc verifyZeroInteractions) ensures that the SUT does not interact with the dummy object. Easy as one-two-three!

Improving the test with JMockit
We can do the same thing using JMockit.

  1. Make a dummy object for Pawner
  2. Ensure that the SUT does not interact with the dummy object

The test now looks like this.

@Injectable
Pawner dummyPawner;

@Test
public void check_in_sheet_should_add_line_item() {
  final int NUMBER_OF_ITEMS = 1;
  Asset asset = new Asset("Dummy Asset Name");
  CheckInSheet checkInSheet = new CheckInSheet(dummyPawner);

  checkInSheet.add(asset);

  List<Asset> lineItems = checkInSheet.getLineItems();
  assertEquals("number of items on the check in sheet", NUMBER_OF_ITEMS, lineItems.size());
  assertEquals("the right item on the check in sheet", asset, lineItems.get(0));

  new FullVerifications(dummyPawner) {};
}

We create a dummy object with the statement @Injectable Pawner dummyPawner; (see JavaDoc @Injectable) and use it to instantiate the CheckInSheet. The last statement new FullVerifications(dummyPawner) {}; (see JavaDoc FullVerifications) ensures that the SUT does not interact with the dummy object. Again, easy as one-two-three!

Which framework to use?
There are too many good mocking frameworks out there to make a dogmatic claim that one of them is better than the rest. Yet one thing in these two examples of Mockito and JMockit stands out. Clarity. Test code should not make you wonder what is being asserted / verified. In this case verifyZeroInteractions(dummyPawner); is preferable to the less than specific new FullVerifications(dummyPawner) {};. But apart from that – though it may sound like a plattitude – it’s best to choose frameworks and tool(s) that fit in your context. In the next post we’ll look at the stub.

Author: David Baak

To code or not to code? That's true.

1 thought on “Test Doubles: creating a Dummy Object using a mocking framework”

Leave a Reply

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