Reputation: 4799
I have a repository which returns objects implementing two interfaces
public interface MyRepository<T extends A & B> extends JpaRepository<T, Long>
List<T> findAll();
...
Using Spring I inject all implementations of these into another class, but additionally specifying that the generic type should itself additionally implement a certain interface C
class X {
@Autowired
private List<MyRepository<? extends C> myCRepos;
Note that C is an interface which does not extend A & B, but all the concrete implementations I want injected implement all three interfaces
class MyConcreteClass implements A, B, C
So a public interface ConcreteRepo extends MyRepository<MyConcreteClass>
is correctly found by Spring and injected, as expected in the List
of class X
.
If I now use the findAll
method, its return type is inferred by the IDE as List<? extends C>
.
Why is the return type not rather List<? extends A & B & C>
?
For testing I want to mock this findAll
and so return an object of the correct type, but the following already fails:
List<? extends C> someTestList = new ArrayList<>();
someTestList.add(new MyConcreteClass()); //
// has error like
// The method add(capture#1-of ? extends C) in the type
// List<capture#1-of ? extends C> is not applicable for the arguments (C)
How should I fix this error?
Finally, I want to mock this whole thing
Mockito.when(myRepo.findAll()).thenReturn(someTestList);
Same question, what should be the type someTestList
and how to create it?
Upvotes: 1
Views: 164
Reputation: 4799
After some more reading on generics, here's the solution. First, as noted by Philipp Wendler, the someTestList
must be typed without a wildcard to be able to actually input something in it.
List<C> someTestList = new ArrayList<>();
someTestList.add(new MyConcreteClass()); //
Additionally, in the call to Mockito, the compiler needs a hint on the return type:
Mockito.<List<? extends C>>when(myRepo.findAll()).thenReturn(someTestList);
Upvotes: 0
Reputation: 11433
I am not certain about the answer to your first question, but the second question has nothing to do with your complex type hierarchy. Whenever you have a List<? extends Something>
, you will not be able to add something to it, because this basically declares the list as a list of "some unknown type", and Java cannot ensure that MyConcreteClass
is an instance of "some unknown type". You can solve this and your third question by declaring someTestList
as List<MyConcreteClass>
.
Upvotes: 1