3

I want to verify that a exact Collection is passed to a mocked method. This is how I tried to do it:

This is a simple example of my real code, which reproduce exactly the same problem.

import com.google.common.collect.Lists;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.mockito.hamcrest.MockitoHamcrest;

import java.util.Collection;

public class MockTest {

    @Test
    void mockTest() {

        final Collection<String> collection = Mockito.mock(Collection.class);

        collection.addAll(Lists.newArrayList("hello"));

        Mockito.verify(collection).addAll(MockitoHamcrest.argThat(Matchers.contains("hello")));
    }
}

but it doesn't work and I get this compilation error:

Error:(20, 35) java: incompatible types: inference variable T has incompatible bounds
    equality constraints: java.lang.Iterable<? extends E>
    lower bounds: java.util.Collection<? extends java.lang.String>,java.lang.Object

Any idea on why it doesn't work or how can I do it differently?

b1zzu
  • 370
  • 4
  • 17

2 Answers2

1

can you please try below code

@Test
public void mockTest() {

    final Collection<String> collection = Mockito.mock(Collection.class);

    collection.addAll(Lists.newArrayList("hello"));

    Mockito.verify(collection).addAll((Collection<? extends String>) MockitoHamcrest.argThat(Matchers.contains("hello")));
}
Kumar Panchal
  • 186
  • 13
  • Thanks, it works! As mentioned by @loïc-le-doyen the problem is that `addAll` want a `Collection` but `MockitoHamcrest.argThat(Matchers.contains("hello"))` return a `Iterable`. – b1zzu Oct 30 '18 at 16:05
1

For the record, you are not testing anything with this test, as you mock the object under test.

For the sake of the experience though, you face this error because, the Collection#addAll method expects a parameter of type Collection whereas you supply one of type Iterable.

An Iterable object may be a Collection or may be not, so the compiler cannot ensure type safety of this code.

One way to check that your mocked method is called with the right arguments is to use an ArgumentCaptor.

Collection<String> collection = Mockito.mock(Collection.class);

collection.addAll(Lists.newArrayList("hello"));

ArgumentCaptor<Collection<String>> methodParameterCaptor = ArgumentCaptor.forClass(Collection.class);
Mockito.verify(collection).addAll(methodParameterCaptor.capture()); // same as writing verify(collection, times(1)).add ...
assertThat(methodParameterCaptor.getValue()).containsOnly("hello");
Loïc Le Doyen
  • 975
  • 7
  • 16