4

I want to validate the logging made by a helper class, which calls a method with some varargs.

I am using Mockito (1.10.19) to mock the actual logger, and to verify the mocked method is called as expected.

I use an ArgumentCaptor to validate the arguments.

The Mockito.verify validates the number of times the mocked method is called, however, the ArgumentCaptor.getAllValues is returning a single array with all the parameters of all the method calls.

Here is a sample code:

interface Logger
{
    void info(Object... params);
}

@Mock
Logger logger;

public void logMatrix(String[][] matrix)
{
    for (int column = 0; column < matrix.length; column++)
    {
        logger.info(column, " : ", matrix[column]);
    }
}

@Test
public void givenMatrix_whenLogMatrix_thenLogsEachRow() throws Exception
{
    String[][] matrix = {
        {"a", "b"},
        {"c", "d"}
    };

    ArgumentCaptor<Object[]> captor = ArgumentCaptor.forClass(Object[].class);

    logMatrix(matrix);

    // verify the mocked method is called twice
    Mockito.verify(logger, times(2)).info(captor.capture());

    // verify the contents of the calls: expecting two arrays, one for each call 
    assertThat(captor.getAllValues()).hasSize(2);
    // fails !
}

The failure is:

java.lang.AssertionError: 
   Expected size:<2> but was:<6> in:
      <[0, " : ", ["a", "b"], 1, " : ", ["c", "d"]]>
   at TestLogHelper.givenMatrix_whenLogMatrix_thenLogsEachRow(TestLogHelper.java:72)
...

Is it a misuse? or a bug in mockito ?

  • 1
    For varargs, it exists special matchers/argument captors. [See this thread.](http://stackoverflow.com/questions/2631596/how-to-properly-match-varargs-in-mockito) – Jonathan Schoreels Mar 14 '16 at 17:14
  • The issue is not on matching or use of argument captor: the verifiers verifies the method is called twice as expected, with varargs. But when the ArgumentCaptor is used to get the captured values, it returns a list with the 3 arguments of both calls. – Vincent Vandemeulebrouck Mar 15 '16 at 08:20

2 Answers2

3

So after 5 years ops question is still unanswered because there are only workarounds present. These are:

  • If you only have single invocation of tested method you can still use captors like op mentioned using getAllValues() for verification. This is the method recommended for varargs in documentation for latest Mockito 3.8.0
  • If you have multiple invocations you will not be able to tell which argument was passed in which invocation, you will just have them in one list. You will still be able to verify number of invocations. Yet, you might be better using argThat() in this scenario
domaru
  • 348
  • 2
  • 13
0

I think this used to be a bug or some other behavior was intended with getAllValues().

Here there's a discussion on the issue or a similar one: https://github.com/mockito/mockito/issues/584

Your code would work today, or at least the getAllValues() would indeed return a list with size 2, as expected.

Chebi
  • 141
  • 5