Mockito : doAnswer Vs thenReturn

Lesezeit: 4 Minuten

Benutzer-Avatar
Rajkumar Thambu

Ich verwende Mockito für spätere Einheitentests. Ich bin verwirrt, wann ich es verwenden soll doAnswer vs thenReturn.

Kann mir jemand im Detail helfen? Bisher habe ich es mit probiert thenReturn.

Benutzer-Avatar
Roland Wiesleder

Du solltest benutzen thenReturn oder doReturn wenn Sie den Rückgabewert kennen, wenn Sie einen Methodenaufruf simulieren. Dieser definierte Wert wird zurückgegeben, wenn Sie die simulierte Methode aufrufen.

thenReturn(T value) Legt einen Rückgabewert fest, der zurückgegeben wird, wenn die Methode aufgerufen wird.

@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 mockierte Methode aufgerufen wird, zB wenn Sie den Rückgabewert basierend auf den Parametern dieses Methodenaufrufs berechnen müssen.

Verwenden doAnswer() wenn Sie eine void-Methode mit generisch stubben möchten Answer.

Answer gibt eine Aktion an, die ausgeführt wird, und einen Rückgabewert, der zurückgegeben wird, wenn Sie mit dem Mock 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");
}

  • Hallo @Roland Weisleder, aber manchmal sollten Sie einen wertgenerierten inneren Code zurückgeben, der nichts mit Argumenten zu tun hat, z code = UUID.randomUUID()fand ich unmöglich, dies mit umzusetzen mockito.

    – zhuguowei

    5. September 2016 um 3:02 Uhr


  • Wenn Ihr Mock für jeden Aufruf eine neue UUID zurückgeben sollte, würden Sie die implementieren Answer nur mit return UUID.randomUUID();.

    – Roland Weissleder

    5. September 2016 um 9:07 Uhr

  • Kann ich diese Methode aus der neuen Answer-Initialisierung nehmen und sie in eine Methode einfügen, um den Code etwas sauberer zu machen?

    – Linie

    23. Mai 2017 um 10:24 Uhr


  • @Linie Answer ist eine funktionale Schnittstelle, sodass Sie sie mit Java 8 durch einen Lambda-Ausdruck ersetzen könnten. Wenn das nicht sauber genug ist, ist jedes andere übliche und ungewöhnliche Refactoring möglich.

    – Roland Weissleder

    28. Mai 2017 um 16:17 Uhr

  • @ zhuguowei: Gibt einen wertgenerierten inneren Code zurück? Was meinst du damit?

    – Saurabh Patil

    30. November 2018 um 4:50 Uhr

Benutzer-Avatar
aldok

doAnswer und thenReturn dasselbe tun, wenn:

  1. Sie verwenden Mock, nicht Spy
  2. Die Methode, die Sie stubben, gibt einen Wert zurück, keine void-Methode.

Lassen Sie uns diesen BookService verspotten

public interface BookService {
    String getAuthor();
    void queryBookTitle(BookServiceCallback callback);
}

Sie können getAuthor() mit stubben doAnswer und 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 dies bei der Verwendung doAnswerkönnen Sie keine Methode weitergeben when.

// Will throw UnfinishedStubbingException
doAnswer(invocation -> "Joshua").when(service.getAuthor());

Also, wann würden Sie verwenden doAnswer Anstatt von thenReturn? Mir fallen zwei Anwendungsfälle ein:

  1. Wenn Sie die void-Methode “stummeln” möchten.

Mit doAnswer können Sie einige zusätzliche Aktionen beim Methodenaufruf 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);
  1. Wenn Sie Spy anstelle von Mock verwenden

Wenn Sie when-thenReturn auf Spy verwenden, ruft Mockito die echte Methode auf und stummt dann Ihre Antwort. Dies kann ein Problem verursachen, 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 abbrechen.

List list = new LinkedList();
List spy = spy(list);
doAnswer(invocation -> "java").when(spy).get(0);
assertEquals("java", spy.get(0));

Wenn Sie beim Methodenaufruf keine zusätzlichen Aktionen ausführen möchten, können Sie einfach verwenden doReturn.

List list = new LinkedList();
List spy = spy(list);
doReturn("java").when(spy).get(0);
assertEquals("java", spy.get(0));

  • Was ist, wenn die verspottete Methode ungültig ist?

    – Igor Donin

    4. Oktober 2018 um 16:47 Uhr

  • Igor, genau hier kommt doAnswer() ins Spiel und er hat das in der obigen Antwort behandelt.

    – Saurabh Patil

    30. November 2018 um 4:46 Uhr

  • Beim Benutzen doAnswer(new Answer() { ... return null;} Ich erhalte eine Warnung in Eclipse für “Answer ist ein Rohtyp. Verweise auf den generischen Typ Answer sollten parametrisiert werden”. Gibt es eine Möglichkeit, dies zu beheben (außer die Warnung von c zu ignorieren)?

    – LazR

    28. Februar 2019 um 10:51 Uhr

Die einfachste Antwort lautet:

  • Wenn Sie beim Methodenaufruf einen festen Rückgabewert benötigen, sollten wir verwenden dannZurück(…)
  • Wenn Sie eine Operation ausführen müssen oder der Wert zur Laufzeit berechnet werden muss, sollten wir verwenden dann antworte(…)

1018280cookie-checkMockito : doAnswer Vs thenReturn

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy