Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mockito: How to verify one method is called on one mock with different parameter in order

Tags:

java

mockito

I want to test a method of a mock is called in order using different parameters:

I tried to use the following code:

    InOrder inOrder = inOrder(myobject);
    inOrder.verify(myobject).println(any(String.class));
    inOrder.verify(myobject).println(any(String.class));
    inOrder.verify(myobject).println("");
    inOrder.verify(myobject).println("myfolder");
    inOrder.verify(myobject).println("");
    inOrder.verify(myobject).println(System.getProperty("user.home"));

However, this does not seem to work as it gave me an error says

    inOrder.verify(myobject).println(any(String.class));

has been called for 8 times. This is correct through, but it fails to address the order.

I want to check:

  The println method of `myobject` is first called with any string parameter
  Then it is called with any string parameter again
  Then it is called by an empty string
  Then it is called by string "myfolder"
  ......

How can I achieve this?

EDIT:

Error message is:

org.mockito.exceptions.verification.VerificationInOrderFailure: 
Verification in order failure:
printWriter.println(<any>);
Wanted 1 time:
-> at com.mycompany.MyUnitTest.mytest(MyrUnitTest.java:107)
But was 8 times. 
like image 340
KKKCoder Avatar asked Aug 21 '13 21:08

KKKCoder


2 Answers

Use an argument captor to capture the arguments in all the calls to println, then check each of the captured values that you're interested in.

@Captor ArgumentCaptor<String> stringCaptor;

// ...

@Test public void myTest() {

    // ...

    verify(myobject, 6).println(stringCaptor.capture());
    assertEquals("", stringCaptor.getAllValues()[2]);
    assertEquals("myfolder", stringCaptor.getAllValues()[3]);
    assertEquals("", stringCaptor.getAllValues()[4]);    
    assertEquals(System.getProperty("user.home"), stringCaptro.getAllValues()[5]);
like image 82
Dawood ibn Kareem Avatar answered Oct 20 '22 00:10

Dawood ibn Kareem


David Wallace's solution is the best one I know of that uses Mockito, but remember that mocking isn't always the right tool for the job.

If you can, instead of your mock, pass a PrintWriter(ByteArrayOutputStream) and check that the ByteArrayOutputStream matches the output you expect.

@Test public void yourTest() {
  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  PrintWriter writer = new PrintWriter(baos);
  systemUnderTest.doThing(writer);

  assertTrue(writer.toString().endsWith(
      "\n\nmyfolder\n\n" + System.getProperty(user.home) + "\n"));
}

This is also probably closer to the logic you're actually testing, which is that the output looks the way you expect it, not that the methods were called in exactly the right order. You're then free to refactor any way you'd like, including switching to a MessageFormatter template, or building your newlines into a StringBuilder and calling println once. You're also insulated from anyone who uses any other print or println() call, which would otherwise foul up a Mockito-based test.

You might also use a regex Pattern or Scanner to verify correctness, depending on how specific your needs are. Pattern.quote can help you escape regex substrings if you need to build your expected string programmatically (as you do with user.home here).

like image 38
Jeff Bowman Avatar answered Oct 19 '22 23:10

Jeff Bowman