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.