Mockito and Hamcrest: how to verify invocation of Collection argument? Mockito and Hamcrest: how to verify invocation of Collection argument? java java

Mockito and Hamcrest: how to verify invocation of Collection argument?


You can just write

verify(service).perform((Collection<String>) Matchers.argThat(contains("a", "b")));

From the compiler's point of view, this is casting an Iterable<String> to a Collection<String> which is fine, because the latter is a subtype of the former. At run time, argThat will return null, so that can be passed to perform without a ClassCastException. The important point about it is that the matcher gets onto Mockito's internal structure of arguments for verification, which is what argThat does.


As an alternative one could change the approach to ArgumentCaptor:

@SuppressWarnings("unchecked") // needed because of `List<String>.class` is not a thing// suppression can be worked around by using @Captor on a fieldArgumentCaptor<List<String>> captor = ArgumentCaptor.forClass(List.class);verify(service).perform(captor.capture());assertThat(captor.getValue(), contains("a", "b"));

Notice, that as a side effect this decouples the verification from the Hamcrest library, and allows you to use any other library (e.g. Truth):

assertThat(captor.getValue()).containsExactly("a", "b");


If you get stuck in situations like these, remember that you can write a very small reusable adapter.

verify(service).perform(argThat(isACollectionThat(contains("foo", "bar"))));private static <T> Matcher<Collection<T>> isACollectionThat(    final Matcher<Iterable<? extends T>> matcher) {  return new BaseMatcher<Collection<T>>() {    @Override public boolean matches(Object item) {      return matcher.matches(item);    }    @Override public void describeTo(Description description) {      matcher.describeTo(description);    }  };}

Note that David's solution above, with casting, is the shortest right answer.