Test des rappels avec Mockito

Test des rappels avec Mockito

1. Vue d'ensemble

Dans ce court didacticiel, nous allons nous concentrer surhow to test Callbacks en utilisant le framework de test populaireMockito.

Nous allons explorer deux solutions,firstly using an ArgumentCaptor and then the intuitive doAnswer() method.

Pour en savoir plus sur les bons tests avec Mockito, consultez notre série Mockitohere.

2. Introduction aux rappels

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.

Cette exécution peut être immédiate, comme dans un rappel synchrone, mais plus généralement, elle peut avoir lieu ultérieurement, comme dans un rappel asynchrone.

Un scénario courant pour l'utilisation des rappels estduring service interactions when we need to process the response from a service call.

Dans ce didacticiel, nous utiliserons l'interfaceService ci-dessous en tant que collaborateur dans les cas de test:

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

Dans l'argumentCallback, nous passons une classe qui gérera la réponse en utilisant la méthodereply(T response):

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

2.1. Un service simple

Nous utiliserons également un simpleservice 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);
        }
    });
}

La méthodehandleResponse vérifie si la réponse est valide avant d'ajouter des données à l'objetResponse:

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

Pour plus de clarté, nous avons choisi de ne pas utiliser une expression Java Lamda mais lesservice.doActioncall could also be written more concisely:

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

Pour en savoir plus sur les expressions Lambda, consultezhere.

3. Utilisation d'unArgumentCaptor

Regardons maintenanthow we use Mockito to grab the Callback object using an*ArgumentCaptor*:

@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());
}

Dans cet exemple, nous créons d'abord unActionHandler  avant d'appeler la méthodedoAction de ce gestionnaire. This is simply a wrapper to our Simple Service doAction method call où nous invoquons notre rappel.

Ensuite, nous vérifions quedoAction was a appelé notre instance de service fictive en passantanyString() comme premier argument etcallbackCaptor.capture() as the second, which is where we capture the Callback object. La méthodegetValue() peut ensuite être utilisée pour renvoyer la valeur capturée de l'argument.

Maintenant que nous avons l’objetCallback, nous créons un objetResponse qui est valide par défaut avantcall the reply method directly and assert that the response data has the correct value.

4. Utilisation de la méthodedoAnswer()

Nous allons maintenant examiner uncommon solution for stubbing methods that have callbacks en utilisant lesAnswer object and doAnswer method to stub the void methoddoAction: de Mockito

@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();
}

Et, dans notre deuxième exemple, nous créons d'abord un objetResponse invalide qui sera utilisé plus tard dans le test.

Ensuite, nous configurons lesAnswer sur notre service simulé de sorte que lorsquedoAction est appelé,we intercept the invocation and grab the method arguments using invocation.getArgument(1) pour obtenir l'argumentCallback

La dernière étape consiste à créer l'appel de sableActionHandler doAction qui provoque l'appel deAnswer.

Pour en savoir plus sur les méthodes de stubbing void, consultezhere.

3. Conclusion

Dans ce bref article, nous avons présenté deux méthodes différentes pour tester les rappels lors de tests avec Mockito.

Comme toujours, les exemples sont disponibles dans ceGitHub project.