Learn to write tests that invoke a method multiple times with different arguments – and then verify the method invocations and method arguments separately using the ArgumentCaptor.
1. Verify Multiple Invocations with ArgumentCaptor
The given unit test has mocked the HashMap class and invokes in put(key, value) code twice. It then verifies that the method had been invoked twice. The test further verifies all the different method arguments separately.
@RunWith(MockitoJUnitRunner.class)
public class MockitoExample
{
@Mock
HashMap<String, Integer> hashMap;
@Captor
ArgumentCaptor<String> keyCaptor;
@Captor
ArgumentCaptor<Integer> valueCaptor;
@Test
public void saveTest()
{
hashMap.put("A", 10);
hashMap.put("B", 20);
//1. Verify method was invoked N times
Mockito.verify(hashMap, times(2)).put(keyCaptor.capture(), valueCaptor.capture());
List<String> keys = keyCaptor.getAllValues();
List<Integer> values = valueCaptor.getAllValues();
//2. Verify method argument values as list
assertEquals(Arrays.asList("A", "B"), keys);
assertEquals(Arrays.asList(Integer.valueOf(10), Integer.valueOf(20)), values);
//3. Verify method arguments separately
assertEquals("A", keys.get(0));
assertEquals("B", keys.get(1));
assertEquals(Integer.valueOf(10), values.get(0));
assertEquals(Integer.valueOf(20), values.get(1));
}
}
2. Explanation
To capture and verify all the method arguments passed to a method when it is invoked multiple times, we shall follow the below steps:
- Use
Mockito.verify(mock, times(n))to verify if the method was executed ‘n’ times. - Create as many ArgumentCaptor instances as the number of arguments in the method. In above example, we tested the HashMap which works on key-value pairs, so we created two
ArgumentCaptorinstances – one for key and second for value. - Use
ArgumentCaptor.getAllValues()to retrieve all the values passed to one method parameter during all executions. It returns aListof passed argument values. - We can use
assertEquals(expected, result)to verify that expected multiple arguments match with the retrieved values fromArgumentCaptor.
Happy Learning !!
Hi Lokesh,
Is there something in Mockito — like anytimes(), with Easymock– that allows a developer to specify that this service will be called some undetermined amount of times?
Declan
Looks like it has been rejected in past. May be you can see if
atLeast(0)oratLeastOnce()fits in your requirement.hi. I am writing a test case for a class which like this:
public class A {
public void methodOne(int argument) {
//some operations
methodTwo(argument);
//some operations
}
private void methodTwo(int argument) {
ReportClass report = new ReportClass ();
//use dateTime to perform some operations
}
}
in this case i am not allowed to perform any change in src code but I need to set some attributes to ReportClass. beacuse of this class test case getting failed. I don’t know how to write a test case for this class.
I want one method to return different result after some time eg. 1s. This is for rate limit test. How to mock it?
Hi Lokesh,
I have a class which must be tested with Mockito. De class has two dependent worker classes. Both worker classes are mocked in the test. But each of the two worker classes has the same argument type. How can I capture the two invocations of the two worker classes and check if the worker classes are called with the proper arguments ?
Kind regards,
Bart
Hi Lokesh,
I want to put some static values in either array or hash map and compare them with logs in a CSV document to verify whether those values are being passed. what is the best of doing it
For ex: CSV contains a value like in JSON request and I want to make sure this value is passed whenever the app is run