Reputation: 15009
Assume I want to test code like this:
class ClassToTest
// UsedClass1 contains a method UsedClass2 thisMethod() {}
UsedClass1 foo;
void aMethod()
{
int max = new Random().nextInt(100);
for(i = 0; i < max; i++)
{
foo.thisMethod().thatMethod();
}
}
}
If I have a test like this:
ClassToTest test;
UsedClass1 uc1;
UsedClass2 uc2;
@Test
public void thingToTest() {
test = new ClassToTest();
uc1 = mock(UsedClass1.class);
uc2 = mock(UsedClass2.class);
when(uc1.thisMethod()).thenReturn(uc2);
when(uc2.thatMethod()).thenReturn(true);
test.aMethod();
// I would like to do this
verifyEquals(callsTo(uc1.thisMethod()), callsTo(uc2.thatMethod()));
}
How can I get the number of calls to uc1.thisMethod()
and uc2.thatMethod()
so I can check they were both called the same number of times?
Upvotes: 7
Views: 14630
Reputation: 14149
You can do something like this:
YourService serviceMock = Mockito.mock(YourService.class);
// code using YourService
// details of all invocations including methods and arguments
Collection<Invocation> invocations = Mockito.mockingDetails(serviceMock).getInvocations();
// just a number of calls of any mock's methods
int numberOfCalls = invocations.size();
If you want only the invocations of certain method/param combination you, you can do so with
int specificMethodCall = Mockito.mockingDetails(serviceMock.myMethod(myParam)).getInvocations()
Upvotes: 21
Reputation: 5629
You can use a custom VerificationMode to count the invocations, here you go:
public class InvocationCounter {
public static <T> T countInvocations(T mock, AtomicInteger count) {
return Mockito.verify(mock, new Counter(count));
}
private InvocationCounter(){}
private static class Counter implements VerificationInOrderMode, VerificationMode {
private final AtomicInteger count;
private Counter(AtomicInteger count) {
this.count = count;
}
public void verify(VerificationData data) {
count.set(data.getAllInvocations().size());
}
public void verifyInOrder(VerificationDataInOrder data) {
count.set(data.getAllInvocations().size());
}
@Override
public VerificationMode description(String description) {
return VerificationModeFactory.description(this, description);
}
}
}
And then use it like this (works also with void return types):
@Mock
private Function<String, Integer> callable;
AtomicInteger count= new AtomicInteger(); //here is the actual invocation count stored
countInvocations(callable,count).apply( anyString());
assertThat(count.get(),is(2));
Upvotes: 2
Reputation: 31648
If you know the number of times a method is suppoed to be called you can use the times()
method of Mockito
//for example if had to be called 3 times
verify(uc1, times(3)).thisMethod();
verify(uc2, times(3)).thatMethod();
However, I now see that you call the method a random number of times, so this probably isn't the best answer unless you stub out the random number generator to always return an expected value.
Upvotes: 5
Reputation: 686
You could stub your methods, and increment a counter, like this:
final AtomicInteger countCall1 = new AtomicInteger();
Mockito.doAnswer(new Answer<UsedClass2>() {
@Override
public UsedClass2 answer(InvocationOnMock invocation) throws Throwable {
countCall1.incrementAndGet();
return uc2;
}
}).when(uc1).thisMethod();
Upvotes: 11