Mocking a builder

by Chris Oxley

If an Object delegated to a builder, you may wish to mock that builder to perform a unit test. To avoid NullPointerExceptions you would have to define behaviour for all chained build methods.

The following examples use Mockito.

Here is the laborious way:

IClubBuilder mockClubBuilder = mock(IClubBuilder.class);
when(mockClubBuilder.forLeftHandedGolfer()).thenReturn(mockClubBuilder);
when(mockClubBuilder.forRightHandedGolfer()).thenReturn(mockClubBuilder);
when(mockClubBuilder.withBounce(0)).thenReturn(mockClubBuilder);
when(mockClubBuilder.withLoft(0)).thenReturn(mockClubBuilder);

Wedge wedge = ClubFactory.makeSandWedge(mockClubBuilder);

There is a better way. Using the given class:

public class AnswerWithSelf implements Answer<Object> {

  private final Answer<Object> emptyReturnValues;
  private final Class<?> classToMatchAndReturn;

  public AnswerWithSelf(Class<?> classToMatchAndReturn) {
      this.classToMatchAndReturn = classToMatchAndReturn;
      this.emptyReturnValues = new ReturnsEmptyValues();
  }

  @Override
  public Object answer(InvocationOnMock invocation) throws Throwable {
      Class<?> returnType = invocation.getMethod().getReturnType();
      boolean withSelf = classToMatchAndReturn.equals(returnType);
      return withSelf ? invocation.getMock() 
                      : emptyReturnValues.answer(invocation);
  }
}

You can replace the above mocking with a default answer:

IClubBuilder mockClubBuilder = 
    mock(IClubBuilder.class, new AnswerWithSelf(IClubBuilder.class));

Wedge wedge = ClubFactory.makeSandWedge(mockClubBuilder);

This approach could be used for any chained method call mocking.

Happy mocking.