2016-12-07 3 views
1

Ich versuche, Generika und Platzhalter in Java 8 um mich herum. Aber ich kann nicht verstehen, warum diese Repository-Methode nicht verspotten kann. Der Code ist ziemlich einfach und sollte daher einfach zu reproduzieren sein.Wie kann ich die Rückkehr von einer generischen Wildcard verspotten

Ich habe diese Zusammenstellung Fehler bekam in "thenReturn" Teil des "wenn"

The method thenReturn(Stream<capture#1-of ? extends Something>) in the type 
OngoingStubbing<Stream<capture#1-of ? extends Something>> is not applicable 
for the arguments (Stream<capture#3-of ? extends Something>) 

der Test:

@Test 
public void ItShourReturnStreamFromRepository() { 
    List<Something> list = new ArrayList<Something>(); 
    list.add(new Something()); 
    Stream<? extends Something> stream = list.stream(); 
    when(someRepository.getStream()).thenReturn(stream);  
} 

die Klasse:

public class Something {} 

das Repository :

public interface SomeRepository{ 
    Stream<? extends Something> getStream(); 
} 

Kann mir jemand helfen? Danke!

+1

Befolgen Sie die Empfehlung des [offiziellen Tutorial] (http://docs.oracle.com/javase/tutorial/java/generics/wildcardGuidelines.html): * Die Verwendung eines Platzhalters als Rückgabetyp sollte vermieden werden ... * – Holger

+2

Wie wäre es, der Schnittstelle einen Typ hinzuzufügen? 'Interface SomeRepository {Stream getStream(); } ' –

Antwort

5

Dies ist ein generelles Problem mit Platzhaltertypen. Um zu demonstrieren, es mit einer vereinfachten, Mockito unabhängige Beispiel:

Enum<?> e = Thread.State.BLOCKED; 

// produces "incompatible types: Enum<CAP#1> cannot be converted to Enum<CAP#2>" 
Arrays.asList(e).set(0, e); 

// works since Java 8 
List<Enum<?>> list=Arrays.asList(e); 
list.add(e); 

// works even in older versions 
Arrays.<Enum<?>>asList(e).set(0, e); 

Dies deutet auf eine mögliche Lösungen, die auch mit dem Mockito API funktionieren sollte. Doch für eine API wie die SomeRepository Gestaltung sollten Sie nach dem allgemeinen “Guidelines for Wildcard Use”:

einen Platzhalter als Rückgabetyp verwenden sollten vermieden werden, da es Programmierer zwingt den Code mit Wildcards zu beschäftigen.

Die ? extends im Stream-Element-Typ erzeugt eine Komplikation ohne Nutzen. Sie können immer einen Stream<Something> sogar aus einer Quelle erstellen, die einen spezifischeren Typ aufweist, z.

SubTypeOfSomething subTyped = … 

// from specific values 
Stream<Something> s1 = Stream.of(subTyped); 

// from existing collection 
Set<SubTypeOfSomething> set = Collections.singleton(subTyped); 
// note: this creates the stream directly from the source set 
Stream<Something> s2 = Collections.<Something>unmodifiableSet(set).stream(); 

// if you really unavoidably have a more specifically typed Stream 
Stream<SubTypeOfSomething> s3 = set.stream(); 
Stream<Something> s4 = s3.map(Function.identity()); 

Die Stream<? extends Something> nichts bieten die Stream<Something> nicht bietet.

Es wäre eine andere Sache, wenn die Schnittstelle statt eingegeben wurde, wie folgt RC’s suggestion:

interface SomeRepository<T extends Something> { 
    Stream<T> getStream(); 
} 

Dann brauchen Sie vielleicht einen Platzhalter nicht mehr haben und ein spezieller getippt Strom einen Vorteil bieten.

Verwandte Themen