Ich verwende Mockito für spätere Unit-Tests. Ich bin verwirrt, wann ich doAnswer
vs verwenden soll thenReturn
.
Kann mir jemand im Detail helfen? Bisher habe ich es mit versucht thenReturn
.
Ich verwende Mockito für spätere Unit-Tests. Ich bin verwirrt, wann ich doAnswer
vs verwenden soll thenReturn
.
Kann mir jemand im Detail helfen? Bisher habe ich es mit versucht thenReturn
.
Antworten:
Sie sollten verwenden thenReturn
oder doReturn
wenn Sie den Rückgabewert kennen, wenn Sie einen Methodenaufruf verspotten. Dieser definierte Wert wird zurückgegeben, wenn Sie die verspottete Methode aufrufen.
thenReturn(T value)
Legt einen Rückgabewert fest, der beim Aufruf der Methode zurückgegeben werden soll.
@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
wird verwendet, wenn Sie zusätzliche Aktionen ausführen müssen, wenn eine verspottete Methode aufgerufen wird, z. B. wenn Sie den Rückgabewert basierend auf den Parametern dieses Methodenaufrufs berechnen müssen.
Verwenden
doAnswer()
Sie diese Option, wenn Sie eine void-Methode mit generic stubben möchtenAnswer
.Antwort gibt eine Aktion an, die ausgeführt wird, und einen Rückgabewert, der zurückgegeben wird, wenn Sie mit dem Modell interagieren.
@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
ist eine funktionale Schnittstelle, sodass Sie sie mit Java 8 durch einen Lambda-Ausdruck ersetzen können. Wenn das nicht sauber genug ist, ist jedes andere übliche und ungewöhnliche Refactoring möglich.
doAnswer
und thenReturn
machen Sie dasselbe, wenn:
Lassen Sie uns diesen BookService verspotten
public interface BookService {
String getAuthor();
void queryBookTitle(BookServiceCallback callback);
}
Sie können getAuthor () mit doAnswer
und stubben 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();
Beachten Sie, dass Sie bei Verwendung doAnswer
keine Methode weitergeben können when
.
// Will throw UnfinishedStubbingException
doAnswer(invocation -> "Joshua").when(service.getAuthor());
Also, wann würden Sie doAnswer
anstelle von verwenden thenReturn
? Ich kann mir zwei Anwendungsfälle vorstellen:
Mit doAnswer können Sie beim Aufrufen der Methode einige zusätzliche Aktionen ausführen. Lösen Sie beispielsweise einen Rückruf für queryBookTitle aus.
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);
Bei Verwendung von when-thenReturn on Spy ruft Mockito die echte Methode auf und speichert dann Ihre Antwort. Dies kann zu einem Problem führen, wenn Sie keine echte Methode aufrufen möchten, wie in diesem Beispiel:
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));
Mit doAnswer können wir es sicher stubben.
List list = new LinkedList();
List spy = spy(list);
doAnswer(invocation -> "java").when(spy).get(0);
assertEquals("java", spy.get(0));
Wenn Sie beim Aufrufen der Methode keine zusätzlichen Aktionen ausführen möchten, können Sie diese einfach verwenden 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;}
erhalte ich in Eclipse eine Warnung für "Antwort ist ein Rohtyp. Verweise auf den generischen Typ Antwort <T> sollten parametrisiert werden". Gibt es eine Möglichkeit, dies zu beheben (außer die Warnung von c zu ignorieren)?
code = UUID.randomUUID()
fand ich es unmöglich, dies mit zu implementierenmockito
.