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

Philipp Jardas picture Philipp Jardas · Dec 7, 2013 · Viewed 52.6k times · Source

I'm running into a generics problem with Mockito and Hamcrest.

Please assume the following interface:

public interface Service {
    void perform(Collection<String> elements);
}

And the following test snippet:

Service service = mock(Service.class);

// ... perform business logic

verify(service).perform(Matchers.argThat(contains("a", "b")));

So I want to verify that my business logic actually called the service with a collection that contains "a" and "b" in that order.

However, the return type of contains(...) is Matcher<Iterable<? extends E>>, so Matchers.argThat(...) returns Iterable<String> in my case, which naturally does not apply to the required Collection<String>.

I know that I could use an argument captor as proposed in Hamcrest hasItem and Mockito verify inconsistency, but I would very much like not to.

Any suggestions! Thanks!

Answer

Dawood ibn Kareem picture Dawood ibn Kareem · Dec 11, 2013

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.