I have a below scenario when setView is called then Presenter fetches some data over the network on a new thread. Test fails by giving this reason - Actually, there were zero interactions with this mock. But it should pass if interaction gets verified.
Testcase
@Test
public void checkUnoRate() {
ratePresenter.setView(rateView,Constants.UNO);
verify(rateView,times(1)).showRate(new Rate());
}
Inside "ratePresenter.setView"
Call<UnoRate> call1 = ratesAPI.getUnoRate();
call1.enqueue(new Callback<UnoRate>() {
@Override
public void onResponse(Call<UnoRate> call,Response<UnoRate> response) {
UnoRate unoRate = response.body();
Rate rate = new Rate();
rate.setBuyRate(unoRate.getBuy());
rate.setSellRate(unoRate.getSell());
rate.setFee(0);
rateView.showRate(rate);
}
});
One very simple solution is to use Mockito's verification with timeout feature. This will retry the verification repeatedly up until the timeout, looking for the condition to pass at some point or another.
The docs, however, warn against it: "This feature should be used rarely - figure out a better way of testing your multi-threaded system." This is probably because you're introducing a new aspect--time--as a proxy for the thing you really want to check, which is that all of the queues have been processed. You could even imagine a busy enough VM where a conservative timeout could cause the test to flake in automated testing systems but that works fine on development machines.
If feasible, you could switch your
ratesAPI
to use a synchronous executor, or instead you could add methods needed to your API accessor to block the test thread until all calls have returned asynchronously:Or, to remove multithreading and external API interactions from your test, simulate the callback synchronously:
As a side note, eventually you'll probably want to verify against a different parameter than
new Rate()
. Mockito compares viaequals
methods when not using Mockito matchers.