2018. február 12., hétfő

Checking parameter of a mocked method call with Mockito


If you are using Mockito, it is sometimes useful to check the parameter state of a method passed to a mocked method call. I use it in the following cases

  • DAO method, like create or update is called in the code. I  want to check, if the entity has been set correctly before writing into the database, but I do not want to use integration test with memory database for it. (With memory database I would be able to read the entity after writing it out, and check the new state)
  • I want to collect the parameters of subsequent calls into a list, in order to analyse them later on. 

To achieve the required functionality, you can implement a custom Answer object for the method invocation and pass it to the then() method.



import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;

...

@Mock
private GatewayDeviceXmlVersionDao gatewayDeviceXmlVersionDao;

@InjectMocks
private ReadDeviceXmlFileVersionResponseProcessor processor;

...
@Test
public void testProcess_storesUnknownVersionWhenFailed() throws Exception {
 when(gatewayDeviceXmlVersionDao.findByGatewayId(Mockito.eq(GATEWAY_ID))).thenReturn(null);

 Answer<?> answer = new Answer<Object>() {
  @Override
  public Object answer(InvocationOnMock invocation) throws Throwable {
   GatewayDeviceXmlVersion versionSaved = invocation.getArgument(0);
   assertThat(versionSaved.getCurrentDeviceXmlVersion(), equalTo(ReadDeviceXmlFileVersionResponse.UNKNOWN_VERSION));
   assertThat(versionSaved.getUpdateStatus(), equalTo(UpdateProcessStatus.OK));
   return null;
  }
 };
 // checking state of version saved into the database
 when(gatewayDeviceXmlVersionDao.save(Mockito.any(GatewayDeviceXmlVersion.class))).then(answer);

 processor.process();
}


As you can see, you can get the parameter from the invocation object, ans do whatever you want with it.

With this solution, you can avoid to create a a custom mocked implementation. You can use the mocked object as before. You can call other methods on it, using Mockito other functions.