2013-04-11 11 views
40

Sto usando mockito 1.9.5. Ho il codice seguente:mocking un metodo che restituisce generici con caratteri jolly utilizzando mockito

public class ClassA { 

public List<? extends MyInterface> getMyInterfaces() { 
    return null; 
} 

public static void testMock() { 
    List<MyInterface> interfaces = new ArrayList<>(); 
    ClassA classAMock = mock(ClassA.class); 
    when(classAMock.getMyInterfaces()).thenReturn(interfaces);  
} 

ottengo un errore di compilazione per il thenReturn(interfaces) dicendo:

"The method thenReturn(List<capture#1-of ? extends MyInterface>) in the type 
OngoingStubbing<List<capture#1-of ? extends MyInterface>> is not applicable for the arguments 
(List<MyInterface>)" 

Tuttavia, quando uso il metodo di Mockito thenAnswer, non ottengo l'errore. Qualcuno può dirmi cosa sta succedendo? Perché ottengo l'errore quando utilizzo il metodo thenReturn? C'è qualche altro modo per risolvere questo problema quando ClassA è fornito da una terza parte e non può essere modificato?

+0

Non si dovrebbe avere il carattere jolly nel tipo di ritorno di 'getMyInterfaces'. Non è una buona pratica, perché i clienti di quella API devono gestire una wildcard di cui non sanno nulla. – SpaceTrucker

+1

Non controllo questa API. È dato da una terza parte. – user1504992

+5

@SpaceTrucker Penso che avere un tipo di ritorno come 'Elenco 'è una cosa perfettamente sensata da fare. Significa che tu (come il chiamante del metodo) puoi ottenere gli oggetti 'MyInterface' dalla lista, ma non puoi inserire nulla in esso. –

risposta

49

MODIFICA: a partire da Mockito 1.10.x, i tipi di generica incorporati nella classe vengono ora utilizzati da Mockito per gli stub profondi. vale a dire.

public interface A<T extends Observer & Comparable<? super T>> { 
    List<? extends B> bList(); 
    T observer(); 
} 

B b = deep_stubbed.bList().iterator().next(); // returns a mock of B ; mockito remebers that A returns a List of B 
Observer o = deep_stubbed.observer(); // mockito can find that T super type is Observer 
Comparable<? super T> c = deep_stubbed.observer(); // or that T implements Comparable 

Mockito fa del suo meglio per ottenere informazioni sul tipo che il compilatore incorpora, ma quando si applica la cancellazione, non Mockito può fare altro che restituire una finta di Object.


originale: Beh, questo è più di un problema con i farmaci generici che con Mockito. Per i generici, dovresti leggere cosa ha scritto su di loro Angelika Langer. E per l'argomento corrente, ad esempio i caratteri jolly, leggi questo section.

Ma in breve, quello che si potrebbe utilizzare è l'altra sintassi Mockito per aiutare con la vostra situazione attuale:

doReturn(interfaces).when(classAMock).getMyInterfaces(); 

o con l'alias BDD:

willReturn(interfaces).given(classAMock).getMyInterfaces(); 

Tuttavia, si potrebbe scrivere involucri che sono più generici. Ciò aiuterà i futuri sviluppatori a lavorare con la stessa API di terze parti.


Come nota a margine: non si deve usare il tipo di mock che non si possiede, può portare a molti errori e problemi. Invece dovresti avere un involucro. DAO e repository, ad esempio, rappresentano tale idea, uno deriderà l'interfaccia DAO o repository, ma non la roba JDBC/JPA/hibernate. Ci sono molti post del blog a tale proposito:

+0

Grazie anche per i collegamenti penetranti! – thSoft

+0

La sintassi 'doReturn' non è sicura dal testo, tuttavia (è possibile restituire qualsiasi cosa, non solo un elenco di qualcosa). (Anche se durante questa configurazione si ottiene comunque un'eccezione, ma non se si inserisce un diverso tipo di elenco.) –

+0

@ PaŭloEbermann In effetti, ciò è dovuto al tipo di cancellazione. In questo caso il controllo viene eseguito in fase di runtime. L'altro modulo può essere controllato in fase di compilazione. – Brice

36

Un'altra soluzione (anche se meno leggibile) è quello di qualificare la chiamata di metodo statico when per associare il carattere jolly:

Mockito.<List<? extends MyInterface>>when(classAMock.getMyInterfaces()).thenReturn(interfaces); 
+8

Questa è magia nera, ma funziona perfettamente. Grazie –

+0

Questo è l'unico che ha funzionato per me. – gladed

Problemi correlati