Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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!

like image 286
Philipp Jardas Avatar asked Dec 07 '13 12:12

Philipp Jardas


People also ask

How do you verify a method called in Mockito?

Mockito verify() method can be used to test number of method invocations too. We can test exact number of times, at least once, at least, at most number of invocation times for a mocked method. We can use verifyNoMoreInteractions() after all the verify() method calls to make sure everything is verified.

How do you use argument matchers in Mockito?

Mockito uses equal() as a legacy method for verification and matching of argument values. In some cases, we need more flexibility during the verification of argument values, so we should use argument matchers instead of equal() method. The ArgumentMatchers class is available in org. mockito package.

Which method in Mockito verifies that no interaction has happened with a mock in Java?

Mockito verifyZeroInteractions() method It verifies that no interaction has occurred on the given mocks. It also detects the invocations that have occurred before the test method, for example, in setup(), @Before method or the constructor.


1 Answers

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.

like image 119
Dawood ibn Kareem Avatar answered Oct 01 '22 22:10

Dawood ibn Kareem