Callbacks mit Mockito testen

Callbacks mit Mockito testen

1. Überblick

In diesem kurzen Tutorial konzentrieren wir uns aufhow to test Callbacks unter Verwendung des beliebten TestframeworksMockito.

Wir werden zwei Lösungen untersuchen,firstly using an ArgumentCaptor and then the intuitive doAnswer() method.

Weitere Informationen zum Testen mit Mockito finden Sie in unseren Mockito-Serienhere.

2. Einführung in Callbacks

A callback is a piece of code that is passed as an argument to a method, which is expected to call back (execute) the argument at a given time.

Diese Ausführung kann wie bei einem synchronen Rückruf sofort erfolgen, in der Regel jedoch zu einem späteren Zeitpunkt als bei einem asynchronen Rückruf.

Ein häufiges Szenario für die Verwendung von Rückrufen istduring service interactions when we need to process the response from a service call.

In diesem Tutorial verwenden wir die unten gezeigteService-Schnittstelle als Kollaborateur in Testfällen:

public interface Service {
    void doAction(String request, Callback callback);
}

Im ArgumentCallbackübergeben wir eine Klasse, die die Antwort mit der Methodereply(T response)verarbeitet:

public interface Callback {
    void reply(T response);
}

2.1. Ein einfacher Service

Wir verwenden auch ein einfachesservice example to demonstrate how to pass and invoke the callback:

public void doAction() {
    service.doAction("our-request", new Callback() {
        @Override
        public void reply(Response response) {
            handleResponse(response);
        }
    });
}

Die MethodehandleResponseprüft, ob die Antwort gültig ist, bevor dem ObjektResponseeinige Daten hinzugefügt werden:

private void handleResponse(Response response) {
    if (response.isValid()) {
        response.setData(new Data("Successful data response"));
    }
}

Aus Gründen der Übersichtlichkeit haben wir uns dafür entschieden, keinen Java Lamda-Ausdruck zu verwenden, sondernservice.doActioncall could also be written more concisely:

service.doAction("our-request", response -> handleResponse(response));

Um mehr über Lambda-Ausdrücke zu erfahren, schauen Sie sichhere an.

3. Mit einemArgumentCaptor

Schauen wir uns nunhow we use Mockito to grab the Callback object using an*ArgumentCaptor*: an

@Test
public void givenServiceWithValidResponse_whenCallbackReceived_thenProcessed() {
    ActionHandler handler = new ActionHandler(service);
    handler.doAction();

    verify(service).doAction(anyString(), callbackCaptor.capture());

    Callback callback = callbackCaptor.getValue();
    Response response = new Response();
    callback.reply(response);

    String expectedMessage = "Successful data response";
    Data data = response.getData();
    assertEquals(
      "Should receive a successful message: ",
      expectedMessage, data.getMessage());
}

In diesem Beispiel erstellen wir zuerst einActionHandler , bevor wir diedoAction-Methode dieses Handlers aufrufen. This is simply a wrapper to our Simple Service doAction method call, wo wir unseren Rückruf aufrufen.

Als nächstes überprüfen wir, obdoAction unsere Mock-Service-Instanz aufgerufen hat undanyString() als erstes Argument undcallbackCaptor.capture() as the second, which is where we capture the Callback object übergeben hat. Die MethodegetValue() kann dann verwendet werden, um den erfassten Wert des Arguments zurückzugeben.

Nachdem wir dasCallback-Objekt erhalten haben, erstellen wir einResponse-Objekt, das standardmäßig gültig ist, bevor wircall the reply method directly and assert that the response data has the correct value.

4. Verwenden derdoAnswer()-Methode

Jetzt betrachten wir eincommon solution for stubbing methods that have callbacks mit MockitosAnswer object and doAnswer method to stub the void methoddoAction:

@Test
public void givenServiceWithInvalidResponse_whenCallbackReceived_thenNotProcessed() {
    Response response = new Response();
    response.setIsValid(false);

    doAnswer((Answer) invocation -> {
        Callback callback = invocation.getArgument(1);
        callback.reply(response);

        Data data = response.getData();
        assertNull("No data in invalid response: ", data);
        return null;
    }).when(service)
        .doAction(anyString(), any(Callback.class));

    ActionHandler handler = new ActionHandler(service);
    handler.doAction();
}

In unserem zweiten Beispiel erstellen wir zuerst ein ungültigesResponse-Objekt, das später im Test verwendet wird.

Als nächstes richten wirAnswer in unserem Mock-Service so ein, dass beim Aufruf vondoActionwe intercept the invocation and grab the method arguments using invocation.getArgument(1) das ArgumentCallback erhält

Der letzte Schritt besteht darin, den SandaufrufActionHandler doAction zu erstellen, wodurch dieAnswer aufgerufen werden.

Um mehr über Stubbing-Void-Methoden zu erfahren, schauen Sie sichhere an.

3. Fazit

In diesem kurzen Artikel haben wir zwei verschiedene Vorgehensweisen zum Testen von Rückrufen beim Testen mit Mockito behandelt.

Wie immer sind die Beispiele inGitHub project verfügbar.