Mockito - differenza tra doReturn () e when ()


196

Attualmente sto usando Mockito per deridere i miei oggetti del livello di servizio in un'applicazione Spring MVC in cui voglio testare i miei metodi Controller. Tuttavia, mentre leggevo i dettagli di Mockito, ho scoperto che i metodi doReturn(...).when(...)sono equivalenti when(...).thenReturn(...). Quindi, la mia domanda è: qual è il punto di avere due metodi che fanno la stessa cosa o qual è la sottile differenza tra doReturn(...).when(...)e when(...).thenReturn(...)?

Qualsiasi aiuto sarebbe apprezzato.


1
Il javadoc ha alcuni casi in cui doReturn()è utile.
Sotirios Delimanolis,

5
Penso che una delle differenze principali sia che doReturn (...). Quando (..) è più vecchio e non è quel tipo sicuro e quindi possiamo usarlo a volte quando il compilatore continua a lamentarsi del casting. The when (..). ThenReturn (..) è molto meglio in termini di sicurezza del tipo
user2511882

Risposte:


227

Le due sintassi per lo stub sono approssimativamente equivalenti. Tuttavia, puoi sempre usare doReturn/whenper il mozzicone; ma ci sono casi in cui non puoi usare when/thenReturn. Stubbing metodi vuoti è uno di questi. Altri includono l'uso con spie Mockito e lo stub dello stesso metodo più di una volta.

Una cosa che when/thenReturnti dà, doReturn/whenno, è la verifica del tipo del valore che stai restituendo, al momento della compilazione. Tuttavia, credo che questo non abbia quasi alcun valore: se hai sbagliato il tipo, lo scoprirai non appena eseguirai il test.

Consiglio vivamente di utilizzare solo doReturn/when. Non ha senso apprendere due sintassi quando si farà.

Potresti fare riferimento alla mia risposta in Formare "grammatiche" di Mockito , una risposta più dettagliata a una domanda strettamente correlata.


16
Non sono d'accordo con David. Mi capita spesso di imbattermi in situazioni in cui restituisco il tipo sbagliato durante l'utilizzo doReturn/whene passo i prossimi minuti a capire cosa è andato storto. Compilare il controllo del tipo di tipo diventa estremamente utile con when/thenReturn.
Saket,

11
Tieni a mente che Mockito ti consiglia di usare use when/thenReturninvece di doReturn/when.
CodyEngel,

2
@CodyEngel e non vi è alcun motivo per tale raccomandazione, a parte quello che ho delineato nelle mie risposte qui e su stackoverflow.com/q/11462697 . Parecchi anni fa, ne ho discusso con Brice Dutheil, che attualmente sta recitando lo sviluppatore principale di Mockito, e, per quanto mi ricordi, concorda. Gli chiederò di pubblicare un commento qui (nessuna garanzia che lo farà).
Dawood ibn Kareem,

18
Il javadoc afferma che doReturn/whenè un compromesso. Il team non consiglia in un modo o nell'altro ma nota che l' when/thenapproccio è più intuitivo, più leggibile e offre il controllo del tempo di compilazione, è l'approccio che ha reso Mockito popolare e facile da usare, non dimenticare che quando la base di codice è condivisa da varie competenze nella tua squadra; tuttavia presenta degli svantaggi per quanto riguarda spie e metodi vuoti.
Brice,

5
Solo per la cronaca: doReturn()ha il grande svantaggio di trasformarsi in una codifica in stile YODA delle chiamate ai metodi. La cosa dopo viene prima scritta per prima. Molte persone leggono da sinistra a destra; quindi ora devi costantemente ricordare di invertire la logica del ritorno-quando nella tua testa.
GhostCat

199

Entrambi gli approcci si comportano in modo diverso se si utilizza un oggetto spiato (annotato con @Spy) anziché un mock (annotato con @Mock):

  • when(...) thenReturn(...) effettua una chiamata reale al metodo prima che venga restituito il valore specificato. Quindi, se il metodo chiamato genera un'eccezione, devi affrontarla / deriderla ecc. Naturalmente ottieni ancora il tuo risultato (quello che definisci in thenReturn(...))

  • doReturn(...) when(...) non chiama affatto il metodo .

Esempio:

public class MyClass {
     protected String methodToBeTested() {
           return anotherMethodInClass();
     }

     protected String anotherMethodInClass() {
          throw new NullPointerException();
     }
}

Test:

@Spy
private MyClass myClass;

// ...

// would work fine
doReturn("test").when(myClass).anotherMethodInClass();

// would throw a NullPointerException
when(myClass.anotherMethodInClass()).thenReturn("test");

37
Questo comportamento funziona solo per gli oggetti spiati, poiché sono "wrapper" di oggetti reali. Nel caso di oggetti derisi, non importa se è quando / thenReturn o doReturn / when. Gli oggetti derisi non chiamano mai metodi reali.
Rafael Orágio,

Potresti fornire maggiori informazioni perché dobbiamo utilizzare questa funzionalità? Non vedo un caso d'uso pratico. L'intento del test è confermare la correttezza del codice in diversi casi d'uso. Se il calll del metodo genera un test di eccezione dovrebbe generare un'eccezione, non restituire un valore
Gleichmut

@Gleichmut Questo era uno scenario ipotetico, in cui mostro l'utilizzo / il vantaggio di doReturn. In una vera applicazione, un metodo che restituisce solo un'eccezione non ha ovviamente senso ... ma hai metodi (probabilmente non così sottili come questo) che possono generare eccezioni in determinate condizioni ..
Akcasoy

1
Solo per chiarimenti: il metodo when (). ThenReturn () - il metodo chiama il metodo effettivo (di una spia - non importa per le beffe) solo una volta. Questo accade nella riga in cui specifichi il comportamento simulato (quando ( myClass.anotherMethodInClass () .thenRet ...). Successivamente il metodo effettivo non viene mai più richiamato. Forse è utile sapere se ti aspettavi qualche logica decoratrice durante la lettura della spiegazione sopra
Jonas il

Questo non sembra un vantaggio doReturn(), sembra un abuso della biblioteca. Lo scopo di spiare invece di puro beffardo è approfittare delle vere chiamate. Avvertono anche di non usare Spie in questo modo: github.com/mockito/mockito/wiki/Using-Spies-(and-Fakes) (e raccomandano invece di estendere la classe e sostituire il metodo)
Matthew Leggi il

13

Il javadoc di Mockito sembra dire perché usare doReturn()invece di when() Usa doReturn () in quelle rare occasioni in cui non puoi usare Mockito.when (Object).

Attenzione che Mockito.when (Object) è sempre consigliato per lo stub perché è un argomento sicuro e più leggibile (specialmente quando si stubba chiamate consecutive).

Ecco quelle rare occasioni in cui doReturn () è utile:

1. Quando spiare oggetti reali e chiamare metodi reali su una spia porta effetti collaterali

List list = new LinkedList(); List spy = spy(list);

// Impossibile: il metodo reale è chiamato così spy.get (0) genera IndexOutOfBoundsException (l'elenco è ancora vuoto)

when(spy.get(0)).thenReturn("foo");

// Devi usare doReturn () per lo stub: doReturn("foo").when(spy).get(0);

2. Sostituzione di una precedente eliminazione di eccezioni:

when(mock.foo()).thenThrow(new RuntimeException());

// Impossibile: il metodo foo () basato sull'eccezione viene chiamato in modo da generare RuntimeException. when(mock.foo()).thenReturn("bar");

// Devi usare doReturn () per lo stub:

doReturn("bar").when(mock).foo(); Gli scenari sopra mostrano un compromesso dell'elegante sintassi di Mockito. Tuttavia, gli scenari sono molto rari. Lo spionaggio dovrebbe essere sporadico e prevalente la soppressione delle eccezioni è molto rara. Per non parlare del fatto che in generale l'eccesso di stub è un potenziale odore di codice che evidenzia troppi stub.


6

Continuando questa risposta , c'è un'altra differenza che se si desidera che il metodo restituisca valori diversi, ad esempio quando viene chiamato per la prima volta, viene chiamato per la seconda volta ecc., È possibile passare valori, ad esempio ...

PowerMockito.doReturn(false, false, true).when(SomeClass.class, "SomeMethod", Matchers.any(SomeClass.class));

Quindi restituirà false quando il metodo viene chiamato nello stesso caso di test e quindi restituirà nuovamente false e infine true.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.