How verify the order of mock methods in JUnit

I have this class with these structure and i need test the behaviour of OnRequestListOfLunchsFinished interface

@Override
public void getListOfLunchs(final OnRequestListOfLunchsFinished callback) {

    zip().onErrorResumeNext(new Function<Throwable, ObservableSource<? extends LunchServiceResponse>>() {

        @Override
        public ObservableSource<? extends LunchServiceResponse> apply(@NonNull Throwable throwable) throws Exception {
            callback.onError(new RuntimeException(throwable));
            callback.onEnd();

            return Observable.empty();
        }

    }).subscribe(new Consumer<LunchServiceResponse>() {

        @Override
        public void accept(LunchServiceResponse response) throws Exception {
            List<Lunch> result = new ArrayList<>();

            List<IngredientResponseVO> ingredients = response.getIngredients();
            Map<Integer, Ingredient> hash = new HashMap<Integer, Ingredient>();

            for (IngredientResponseVO vo : ingredients)
                hash.put(vo.id, new Ingredient(vo.id, vo.name, new BigDecimal(vo.price.toString()), vo.image));

            for(InfoLunchResponseVO vo: response.getLunch()){
                Lunch lunch = new Lunch();
                lunch.setId(vo.id);
                lunch.setImage(vo.image);
                lunch.setName(vo.name);

                for(Integer id : vo.ingredients){
                    Ingredient ingredient = hash.get(id);
                    lunch.addIngredient(ingredient);
                }

                result.add(lunch);
            }

            callback.onSuccess(result);
            callback.onEnd();
        }

    });

    callback.onStart();
}

private Observable<LunchServiceResponse> zip(){
    return Observable.zip(getRequestOfListOfLunchs(), getRequestOfListOfIngredients(), new BiFunction<List<InfoLunchResponseVO>, List<IngredientResponseVO>, LunchServiceResponse>() {

        @Override
        public LunchServiceResponse apply(@NonNull List<InfoLunchResponseVO> infoLunchResponseVOs, @NonNull List<IngredientResponseVO> ingredientResponseVOs) throws Exception {
            return new LunchServiceResponse(infoLunchResponseVOs, ingredientResponseVOs);
        }

    });
}

i have this test method

@Test
public void teste(){
    List<IngredientResponseVO> ingredients = Collections.emptyList();
    List<InfoLunchResponseVO> lunchs = Collections.emptyList();

    when(mockApi.getListOfIngredients()).thenReturn(Observable.just(ingredients));
    when(mockApi.getLunchs()).thenReturn(Observable.just(lunchs));

    mockImplementation.getListOfLunchs(callback);

    InOrder order = inOrder(callback);

    order.verify(callback).onStart();
    order.verify(callback).onSuccess(anyList());
    order.verify(callback).onEnd();

    order.verifyNoMoreInteractions();
}

but i am receiving the exception:

org.mockito.exceptions.verification.VerificationInOrderFailure: 
Verification in order failure
Wanted but not invoked:
callback.onSuccess(<any>);

if i do this:

callback.onStart();
callback.onSuccess(Collections.<Lunch>emptyList());
callback.onEnd();

InOrder order = inOrder(callback);

order.verify(callback).onStart();
order.verify(callback).onSuccess(anyList());
order.verify(callback).onEnd();

order.verifyNoMoreInteractions();

this works.

how verify only calls of my mock callback?

You just must not use the InOrder object.

mockImplementation.getListOfLunchs(callback);

Mockito.verify(callback).onStart();
Mockito.verify(callback).onSuccess(anyList());
Mockito.verify(callback).onEnd();

Mockito.verifyNoMoreInteractions();

AFAICS the issue is not with the test but with your reading of the test results (jumping ahead: I believe it found a bug in your code).

Probably in the real code your getListOfIngredients and getLunchs do some network requests i.e. they are asynchronous to the call to getListOfLunchs and (zip inside of it). Thus in the real code onStart is called immediately on the caller thread while onSucess and onEnd are called later. However in your test you mock those API calls with very synchronous Observable.just and thus the order of execution is different: first onSuccess is called, then onEnd and finally onStart (you can easily validate this if you substitute your mocked callback with a custom one that just logs method name in every call).

You probably expeceted that since you use verifyNoMoreInteractions you would get a error about wrong order of onStart. Unfortunatelly this is not how it works. Since your order verifications are specified earlier, they are checked earlier. And in those checks there is yet no restriction of “no more”. So what happens is roughly following:

  1. onSucess is called. InOrder check ignores it because there was no onStart yet
  2. onEnd is called. InOrder check ignores it because there was no onStart yet
  3. onStart is called. This matches what InOrder expects and now it waits for onSucess. However this (second) onSuccess never comes and this is exactly what the error says.

So what to do? First of all I’d like to say that IMHO this failed test did find a very real bug in your code. Assume that at some point in the future someone added a caching layer to your API so sometimes getListOfIngredients and getLunchs return immediately with a synchronous result. In such case your code breaks contract of the OnRequestListOfLunchsFinished that onStart should be called first. So the proper way is to fix your code. An obvious but possible wrong way is to move the line

callback.onStart();

to the start of the method. (Why it is possibly wrong? Can your zip throw an Exception? If it does, what happens to the state of the callback?). Another way is to do the same as you do with onEnd i.e. copy it inside both success and error handling code in proper order.