Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test in Mockito for specific order of calls with same arguments?

I want to verify the specific order in which characters to ensure that they aren't getting garbled. I tried writing it using InOrder but it seems not to work, or at least in Mockito 1.8.5.

@Test
public void inOrderTest() throws IOException{
    final String message = "Hello World!\n";

    for( char c : message.toCharArray() )
        mockWriter.write( c );

    final InOrder inOrder = inOrder( mockWriter );
    for( char c : message.toCharArray() )
        inOrder.verify( mockWriter ).write( c );
    inOrder.verifyNoMoreInteractions();
}

The test above fails with the message:

Verification in order failure:
mockWriter.write(108);
Wanted 1 time:
-> at     org.bitbucket.artbugorski.brainfuj.interpreter.InterpreterTest.inOrderTest(InterpreterTest.java:62)
But was 3 times. Undesired invocation:
-> at org.bitbucket.artbugorski.brainfuj.interpreter.InterpreterTest.inOrderTest(InterpreterTest.java:58)

How does one write a Mockito test for that?


EDIT: Filed as bug http://code.google.com/p/mockito/issues/detail?id=296

like image 905
Sled Avatar asked Dec 04 '11 02:12

Sled


People also ask

Which mock type the order of the method calls matter?

Mockito provides Inorder class which takes care of the order of method calls that the mock is going to make in due course of its action.

Can we mock same method twice?

We can stub a method with multiple return values for the consecutive calls.

Does Mockito verify use equals?

Mockito verifies argument values in natural java style: by using an equals() method.

How verify method works in Mockito?

Mockito verify() method can be used to test number of method invocations too. We can test exact number of times, at least once, at least, at most number of invocation times for a mocked method. We can use verifyNoMoreInteractions() after all the verify() method calls to make sure everything is verified.


2 Answers

My apologies to the previous respondents; but in my opinion, using an Answer flies a little in the face of one of the basic ideas of Mockito, namely that stubbing and verifying are two completely separate processes. Mockito has features for stubbing and features for verification, and the makers of Mockito have made an effort to keep the two separate. Answers are intended for stubbing; and whereas there are a few cases where an Answer is the best way to verify, I don't believe this is one of them.

I would use an ArgumentCaptor instead of an Answer. I would write a method like this in the test class, then call it with "Hello world" as the argument. Note that I haven't tested this, so it may contain typos.

private void verifyCharactersWritten( String expected ){
    ArgumentCaptor<Character> captor = ArgumentCaptor.forClass( Character.class ); 
    verify( mockWriter, times( expected.length())).write( captor.capture());
    assertEquals( Arrays.asList( expected.toCharArray()), captor.getAllValues());
}

Hope this helps.

like image 141
Dawood ibn Kareem Avatar answered Sep 28 '22 07:09

Dawood ibn Kareem


Verification in order is a separate concept from how many times something is done, so when you get to the 'l' and tell Mockito to verify that it happened, it passes the in-order check, but fails because the 'l' call was made three times, and you (implicitly) told it to expect it only one time. It's a quirk I've hit before in Mockito, but pretty much any time it happens, I end up deciding that my test is poorly written, and when I fix it, the problem goes away. In your case, I'd say it's way overkill to verify each character written to a Writer. If you want to verify a message got sent correctly, you should be comparing the input message to the output message. In your example, that might entail using a StringWriter instead of mocking a writer. Then the end of your test just looks like

assertThat(stringWriter.toString(), equalTo(message));

If you really have to do what you're doing, all I can suggest is digging into the Mockito code to see if there's a way to make it happen and possibly filing a bug report to see what they say about it.

like image 29
Ryan Stewart Avatar answered Sep 28 '22 07:09

Ryan Stewart