Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Verify mock methods got called in exact order using Mockito.inOrder

I'm trying to test the method on mocked object getting called in the expected order or not. Below is the simplified example:

@Test
public void test() {
    List<String> mockedList = Mockito.mock(List.class);

    for (int i = 0; i < 5; i++) {
        mockedList.add("a");
        mockedList.add("b");
        mockedList.add("c");
    }

    // I want only this to pass.
    InOrder inOrder1 = Mockito.inOrder(mockedList);
    inOrder1.verify(mockedList).add("a");
    inOrder1.verify(mockedList).add("b");
    inOrder1.verify(mockedList).add("c");

    // I want this to fail.
    InOrder inOrder2 = Mockito.inOrder(mockedList);
    inOrder2.verify(mockedList).add("c");
    inOrder2.verify(mockedList).add("b");
    inOrder2.verify(mockedList).add("a");
}

Although the verifying order (c -> b -> a) is different from the invocation order (a -> b -> c), this test passes. This is because Mockito verifies if method2 called anywhere AFTER method1, but not immediately (i.e., no other method called in between). As I'm adding elements multiple times, this is very much possible. Which means, Mockito InOrder passes for b -> a -> c -> a -> c -> b -> c -> b -> a ...

But I want this to fail, and make sure the order is always a -> b -> c -> a -> b -> c -> a -> b -> c ...

Update: Proper way to verify is to verify the order same number of iterations (summary of accepted answer):

for (int i = 0; i < 5; i++) {
    inOrder1.verify(mockedList).add("a");
    inOrder1.verify(mockedList).add("b");
    inOrder1.verify(mockedList).add("c");
}

// fail the test if we missed to verify any other invocations
inOrder1.verifyNoMoreInteractions();
like image 862
manikanta Avatar asked Sep 01 '25 10:09

manikanta


1 Answers

The thing is that you need to add

inOrder.verifyNoMoreInteractions();

With your loop you generate calls like

  • add(a)
  • add(b)
  • add(c)
  • add(a)
  • add(b)
  • add(c)

When you then check

inOrder.verify(mockedList).add("b");
inOrder.verify(mockedList).add("c");
inOrder.verify(mockedList).add("a");

It matches the calls (add(b), add(c), add(a)). The other calls are not checked.

  • add(a)
  • add(b)
  • add(c)
  • add(a)
  • add(b)
  • add(c)

So I think you have to options: 1) verify all calls a, b, c, a, b, c 2) verify that no more interactions happen to your mock

BTW if you change the verification to

inOrder.verify(mockedList).add("c");
inOrder.verify(mockedList).add("b");
inOrder.verify(mockedList).add("a");

it will fail as it does not match the calls :-)

like image 71
thopaw Avatar answered Sep 04 '25 01:09

thopaw