I am trying to refactor very old Java legacy tests using Mockito (mockito-core)1.10.19 to Mockito 4.
I have in the legacy the following matcher
private static long nonZeroLong() {
return longThat(not(0L));
}
that should provide arg matchers for the following mock
doAnswer(invocation -> {
Runnable originalTask = invocation.getArgumentAt(0, Runnable.class);
Runnable runnable = () -> {
/*
LOCK is need here to emulate waiting on ConcurrentHashMap.compute method.
It is uses `synchronized` block internally, so any technique which can throw
interrupted exception for waiting can't be used here
*/
synchronized (LOCK) {
}
originalTask.run();
scheduledFutureExecuted.set(true);
futureExecutedSignal.countDown();
};
invocation.getArguments()[0] = runnable;
ScheduledFuture res = (ScheduledFuture) invocation.callRealMethod();
scheduledFutureRef.set(res);
return res;
}).when(pool).schedule(any(Runnable.class), nonZeroLong(), any());
I am not mockito-guro but on a very first place I am not sure at all that this original way was suitable at all for this invocation, however it is the original way was done.
Since in Mockito 4 this argument matcher does not exist anymore I refactored it as :
private static long nonZeroLong() {
return longThat(argument -> argument != 0);
}
However I am still not sure what I provide will be the same as the original matcher in the legacy version.
My question is - will my matcher provide same logic as the original one?
CodePudding user response:
Behaviour is the same.
But in your case, you created the custom ArgumentMatcher
.
Better to use mockito Additional Matchers not(eq(value))
private static long nonZeroLong() {
return not(eq(0L));
}
At least they improve readability of errors output and they have flexible implementation for any type.
Mokito matcher output:
Argument(s) are different! Wanted:
bean.print(not(0L)); // We see actual problem
-> at TestObject.testZeroMathers(TestObject.java:28)
Actual invocations have different arguments:
bean.print(0L);
-> at TestObject.testZeroMathers(TestObject.java:26)
Custom matcher output:
Argument(s) are different! Wanted:
bean.print(<custom argument matcher>); // We do not see actual problem
-> at TestObject.testZeroLongThat(TestObject.java:35)
Actual invocations have different arguments:
bean.print(0L);
-> at TestObject.testZeroLongThat(TestObject.java:33)
Example of test:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.AdditionalMatchers.not;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class TestObject {
@Spy
Bean bean = new Bean();
@Test
public void test() {
bean.print(1L);
verify(bean, times(1)).print(nonZeroLong());
verify(bean, times(1)).print(nonZeroLongThat());
}
@Test
public void testZeroMathers() {
bean.print(0L);
verify(bean, times(1)).print(nonZeroLong());
}
@Test
public void testZeroLongThat() {
bean.print(0L);
verify(bean, times(1)).print(nonZeroLongThat());
}
private static long nonZeroLongThat() {
return longThat(argument -> argument != 0);
}
private static long nonZeroLong() {
return not(eq(0L));
}
}
public class Bean {
public void print(Long l) {
System.out.println("Hi, I'm Bean " l);
}
}