I have Java code running inside a CompletableFuture#runAsync block and I want to verify that a specific service is never called during its execution. Normally, verifyNoInteractions(myService) fires immediately, which can lead to false positives. Using verify(myService, timeout(500).times(0)) for each method works, but it’s cumbersome. Is there a cleaner way to achieve a “no interactions” check with a timeout using Mockito?
In my experience, Mockito doesn’t provide a direct verifyNoInteractions with a timeout. However, the closest approach is to explicitly verify that each method was never called with a timeout, like so:
verify(myService, timeout(500).times(0)).someMethod();
verify(myService, timeout(500).times(0)).anotherMethod();
Pros: It works reliably with async code, ensuring that interactions are checked even with a delay.
Cons: It can get verbose if the service has many methods to verify. So, while this method is effective, it can feel like a bit of overhead.
Building on that, here’s a slightly cleaner approach. You can poll for a short period, repeatedly checking that no interactions occurred. This simulates a timeout for no interactions and avoids the verbosity of checking each method individually:
long endTime = System.currentTimeMillis() + 500; // 500ms timeout
while (System.currentTimeMillis() < endTime) {
try {
verifyNoInteractions(myService);
break; // success
} catch (MockitoAssertionError e) {
// wait a bit and retry
Thread.sleep(50);
}
}
Pros: This solution works great if your service has many methods. Plus, you can encapsulate this logic in a utility method to simplify your tests.
Cleaner than explicitly verifying each method individually.
Cons: A bit of polling is involved, but it simplifies your test.
To make this even cleaner and more expressive, you can use the Awaitility library, which is perfect for async tests. With Awaitility, you can easily wait for conditions like “no interactions” within a specified timeout:
import static org.awaitility.Awaitility.await;
await().atMost(Duration.ofMillis(500))
.untilAsserted(() -> verifyNoInteractions(myService));
Pros: This approach is clean and highly expressive. It’s designed for async testing, so it works seamlessly with CompletableFuture or other async code.
No need for verbose checks for each method, a single call to verifyNoInteractions(myService) suffices.
Cons: It requires an additional dependency (Awaitility), but the benefits in terms of readability and ease of use are worth it.