Sto usando Mockito per il servizio successivo di unit test. Sono confuso quando utilizzare doAnswer
vs thenReturn
.
Qualcuno può aiutarmi in dettaglio? Finora l'ho provato con thenReturn
.
Sto usando Mockito per il servizio successivo di unit test. Sono confuso quando utilizzare doAnswer
vs thenReturn
.
Qualcuno può aiutarmi in dettaglio? Finora l'ho provato con thenReturn
.
Risposte:
Dovresti usare thenReturn
o doReturn
quando conosci il valore restituito nel momento in cui deridi una chiamata al metodo. Questo valore definito viene restituito quando si richiama il metodo mocked.
thenReturn(T value)
Imposta un valore restituito da restituire quando viene chiamato il metodo.
@Test
public void test_return() throws Exception {
Dummy dummy = mock(Dummy.class);
int returnValue = 5;
// choose your preferred way
when(dummy.stringLength("dummy")).thenReturn(returnValue);
doReturn(returnValue).when(dummy).stringLength("dummy");
}
Answer
viene utilizzato quando è necessario eseguire azioni aggiuntive quando viene richiamato un metodo deriso, ad esempio quando è necessario calcolare il valore restituito in base ai parametri di questa chiamata al metodo.
Da utilizzare
doAnswer()
quando si desidera bloccare un metodo void con genericAnswer
.La risposta specifica un'azione che viene eseguita e un valore restituito che viene restituito quando si interagisce con il mock.
@Test
public void test_answer() throws Exception {
Dummy dummy = mock(Dummy.class);
Answer<Integer> answer = new Answer<Integer>() {
public Integer answer(InvocationOnMock invocation) throws Throwable {
String string = invocation.getArgumentAt(0, String.class);
return string.length() * 2;
}
};
// choose your preferred way
when(dummy.stringLength("dummy")).thenAnswer(answer);
doAnswer(answer).when(dummy).stringLength("dummy");
}
Answer
just with return UUID.randomUUID();
.
Answer
è un'interfaccia funzionale, quindi con Java 8 potresti sostituirla con un'espressione lambda. Se il non è abbastanza pulito, è possibile qualsiasi altro refactoring usuale e insolito.
doAnswer
e thenReturn
fai la stessa cosa se:
Prendiamo in giro questo BookService
public interface BookService {
String getAuthor();
void queryBookTitle(BookServiceCallback callback);
}
Puoi stub getAuthor () usando doAnswer
e thenReturn
.
BookService service = mock(BookService.class);
when(service.getAuthor()).thenReturn("Joshua");
// or..
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return "Joshua";
}
}).when(service).getAuthor();
Nota che quando usi doAnswer
, non puoi trasmettere un metodo when
.
// Will throw UnfinishedStubbingException
doAnswer(invocation -> "Joshua").when(service.getAuthor());
Quindi, quando useresti doAnswer
invece di thenReturn
? Mi vengono in mente due casi d'uso:
Utilizzando doAnswer è possibile eseguire alcune azioni aggiuntive durante l'invocazione del metodo. Ad esempio, attiva una richiamata su queryBookTitle.
BookServiceCallback callback = new BookServiceCallback() {
@Override
public void onSuccess(String bookTitle) {
assertEquals("Effective Java", bookTitle);
}
};
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
BookServiceCallback callback = (BookServiceCallback) invocation.getArguments()[0];
callback.onSuccess("Effective Java");
// return null because queryBookTitle is void
return null;
}
}).when(service).queryBookTitle(callback);
service.queryBookTitle(callback);
Quando si utilizza quando-allora, il ritorno su Spy Mockito chiamerà il metodo reale e quindi bloccherà la tua risposta. Ciò può causare un problema se non si desidera chiamare il metodo reale, come in questo esempio:
List list = new LinkedList();
List spy = spy(list);
// Will throw java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
when(spy.get(0)).thenReturn("java");
assertEquals("java", spy.get(0));
Usando doAnswer possiamo bloccarlo in sicurezza.
List list = new LinkedList();
List spy = spy(list);
doAnswer(invocation -> "java").when(spy).get(0);
assertEquals("java", spy.get(0));
In realtà, se non vuoi eseguire azioni aggiuntive durante l'invocazione del metodo, puoi semplicemente usare doReturn
.
List list = new LinkedList();
List spy = spy(list);
doReturn("java").when(spy).get(0);
assertEquals("java", spy.get(0));
doAnswer(new Answer() { ... return null;}
ottengo un avviso in Eclipse per "La risposta è di tipo grezzo. I riferimenti al tipo generico Risposta <T> devono essere parametrizzati". C'è un modo per risolvere questo problema (tranne ignorare l'avvertimento di c)?
code = UUID.randomUUID()
, ho trovato impossibile implementarlo conmockito
.