Search code examples
javatestingjunitmockitohamcrest

Matching mutable object without ArgumentCaptor


I have to test a method which uses a mutable object

private final List<LogMessage> buffer;
...
flushBuffer() {
  sender.send(buffer);
  buffer.clear();
}

I need to test that it sends buffers with exact size.
ArgumentCaptor is not applicable because the captured collection is clear by the time of assertion.

Is there a kind of matcher which can reuse Hamcrest's hasSize() and does check right in time of method call?

I would prefer something like this hypothetical collectionWhich matcher:

bufferedSender.flushBuffer();
verify(sender).send(collectionWhich(hasSize(5)));

Solution

  • A lightweight alternative to David's idea: Use an Answer to make a copy at the time of the call. Untested code, but this should be pretty close:

    final List<LogMessage> capturedList = new ArrayList<>();
    // This uses a lambda, but you could also do it with an anonymous inner class:
    // new Answer<Void>() {
    //   @Override public Void answer(InvocationOnMock invocation) { /* ... */ }
    // }
    when(sender.send(any())).thenAnswer(invocation -> {
      List<LogMessage> argument = (List<LogMessage>) invocation.getArguments()[0];
      capturedList.addAll(argument);
    });
    bufferedSender.flushBuffer();
    assertThat(capturedList).hasSize(5);