Java Generics - Method Not Applicable to Mockito Generated Stub

I have an interface ThingsProviderthat I am trying to test with Mockito (simplified version), which is defined as follows:

interface ThingsProvider {
    Iterable<? extends Thing> getThings()
}

Now that I'm going to test it with Mockito, I do the following (again, simplified for the question):

ThingsProvider thingsProvider = mock(ThingsProvider.class);
List<Thing> things = Arrays.asList(mock(Thing.class));
when(thingsProvider.getThings()).thenReturn(things); // PROBLEM IS HERE

Compilation Error Message: The method thenReturn(Iterable<capture#11-of ? extends Thing>) in the type OngoingStubbing<Iterable<capture#11-of ? extends Thing>> is not applicable for the arguments (List<Thing>)

Now, just to pass the test, I change the last line to

when(thingsProvider.getThings()).thenReturn((List)things); // HAHA take THAT generics!

... but this, obviously, would be bad to do in code without testing.

My question (s):

  • Why is this a mistake? I am clearly returning objects that extend Thingwhat the interface expects.
  • Is there a better way to solve this? Maybe define my interface differently? I still have not encountered this problem outside of testing ...

# 2 - , Iterable<Thing>, , , , , , Type mismatch: cannot convert from Iterable<MagicalThing> to Iterable<Thing> - , - ?


, Mockito, Java- №1 :

public static void main(String...args) {
    List<Integer> ints = Arrays.asList(1,2,3);
    blah(ints);

    Foo<Number> foo1 = new Foo<Number>();
    foo1.bar(ints);  // This works

    Foo<? extends Number> foo2 = new Foo<Number>();
    foo2.bar(ints);  // NO COMPILEY!
} 

private static void blah(List<? extends Number> numberList) {
    // something
}

public static class Foo<T> {
    public Object bar(List<? extends T> tList) {
        return null;
    }
}
+4
2

, .

; Iterable<Thing>, ; javadoc, . , , . List<MyThing> => Iterable<Thing>, .


; , .

    foo( arg )

arg , //. Iterable<? extends Thing> , Iterable<CAP#>.

; Mockito - .


- ;

Mockito.<Iterable<? extends Thing>>when(...

, Delimanolis, ( java8 +)

OngoingStubbing<Iterable<? extends Thing>> stub =  when(...

, lambda

static <T> OngoingStubbing<T> whenX( Supplier<T> sup )
{    
    return Mockito.when( sup.get() );
}

whenX(thingsProvider::getThings).thenReturn(things);
// T = Iterable<? extends Thing>

- , , :)

List<Thing> things = ...;

ThingsProvider thingsProvider = ()->things;
+1

OngoingStubbing<Iterable<? extends Thing>> stub =  when(thingsProvider.getThings());
stub.thenReturn(things);

bayou.io

Mockito.<Iterable<? extends Thing>>when(thingsProvider.getThings())
+2

All Articles