web-dev-qa-db-fra.com

Se moquer d'une méthode d'espionnage avec Mockito

J'écris un test unitaire pour une classe FizzConfigurator qui ressemble à:

public class FizzConfigurator {
    public void doFoo(String msg) {
        doWidget(msg, Config.ALWAYS);
    }

    public void doBar(String msg) {
        doWidget(msg, Config.NEVER);
    }

    public void doBuzz(String msg) {
        doWidget(msg, Config.SOMETIMES);
    }

    public void doWidget(String msg, Config cfg) {
        // Does a bunch of stuff and hits a database.
    }
}

Je voudrais écrire un test unitaire simple qui arrête la méthode doWidget(String,Config) (afin qu’elle ne se déclenche pas et ne frappe pas la base de données), mais cela me permet de verify que l’appel doBuzz(String) finit par exécuter doWidget. Mockito semble être le bon outil pour le travail ici.

public class FizzConfiguratorTest {
    @Test
    public void callingDoBuzzAlsoCallsDoWidget() {
        FizzConfigurator fixture = Mockito.spy(new FizzConfigurator());
        Mockito.when(fixture.doWidget(Mockito.anyString(), Config.ALWAYS)).
            thenThrow(new RuntimeException());

        try {
            fixture.doBuzz("This should throw.");

            // We should never get here. Calling doBuzz should invoke our
            // stubbed doWidget, which throws an exception.
            Assert.fail();
        } catch(RuntimeException rte) {
            return; // Test passed.
        }
    }
}

Ceci semble comme un bon plan de match (du moins pour moi). Mais lorsque je commence à coder, je reçois l'erreur suivante du compilateur sur la deuxième ligne de la méthode de test (la ligne Mockito.when(...):

La méthode lorsque (T) dans le type Mockito n'est pas applicable pour les arguments (void)

Je vois que Mockito ne peut pas se moquer d'une méthode qui retourne void. Alors je demande:

  1. Est-ce que j'approche correctement cette configuration de test? Ou y a-t-il une meilleure façon, recommandée par Mockito, de tester que doBuzz appelle doWidget sous le capot? Et
  2. Que puis-je faire à propos du moquage/de la substitution doWidget car il s'agit de la méthode la plus critique de toute ma classe FizzConfigurator?
9
user1768830

Je ne voudrais pas utiliser des exceptions pour tester cela, mais des vérifications. Et un autre problème est que vous ne pouvez pas utiliser when() avec des méthodes qui renvoient void.

Voici comment je le ferais:

FizzConfigurator fixture = Mockito.spy(new FizzConfigurator());
doNothing().when(fixture).doWidget(Mockito.anyString(), Mockito.<Config>any()));
fixture.doBuzz("some string");
Mockito.verify(fixture).doWidget("some string", Config.SOMETIMES);
23
JB Nizet

Ceci est un signe clair que la méthode doWidget devrait appartenir à une autre classe sur laquelle FizzConfigurator dépendrait.

Dans votre test, cette nouvelle dépendance serait une simulation, et vous pourrez facilement vérifier si sa méthode a été appelée avec verify.

0
rafaelportela

Dans mon cas, pour la méthode que j'essayais de stub, je passais dans des correspondeurs incorrects.

Ma signature de méthode (pour la méthode de super classe que j'essayais de stub): String, Object.

Je passais dans:

myMethod("string", Mockito.nullable(ClassType.class)) et obtenir:

Hints: 1. missing thenReturn() 2. you are trying to stub a final method, which is not supported 3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed

Lorsque vous utilisez un matcher dans un autre paramètre, nous devons également en utiliser un pour la chaîne:

myMethod(eq("string"), Mockito.nullable(ClassType.class))

J'espère que cela t'aides!

0
Adrian Elder