Mockito: InvalidUseOfMatchersException

141

J'ai un outil de ligne de commande qui effectue une vérification DNS. Si la vérification DNS réussit, la commande poursuit d'autres tâches. J'essaie d'écrire des tests unitaires pour cela en utilisant Mockito. Voici mon code:

public class Command() {
    // ....
    void runCommand() {
        // ..
        dnsCheck(hostname, new InetAddressFactory());
        // ..
        // do other stuff after dnsCheck
    }

    void dnsCheck(String hostname, InetAddressFactory factory) {
        // calls to verify hostname
    }
}

J'utilise InetAddressFactory pour simuler une implémentation statique de la InetAddressclasse. Voici le code de l'usine:

public class InetAddressFactory {
    public InetAddress getByName(String host) throws UnknownHostException {
        return InetAddress.getByName(host);
    }
}

Voici mon cas de test unitaire:

@RunWith(MockitoJUnitRunner.class)
public class CmdTest {

    // many functional tests for dnsCheck

    // here's the piece of code that is failing
    // in this test I want to test the rest of the code (i.e. after dnsCheck)
    @Test
    void testPostDnsCheck() {
        final Cmd cmd = spy(new Cmd());

        // this line does not work, and it throws the exception below:
        // tried using (InetAddressFactory) anyObject()
        doNothing().when(cmd).dnsCheck(HOST, any(InetAddressFactory.class));
        cmd.runCommand();
    }
}

Exception lors de l'exécution du testPostDnsCheck()test:

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Invalid use of argument matchers!
2 matchers expected, 1 recorded.
This exception may occur if matchers are combined with raw values:
    //incorrect:
    someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
    //correct:
    someMethod(anyObject(), eq("String by matcher"));

Une entrée sur la façon de résoudre ce problème?

devang
la source

Réponses:

283

Le message d'erreur décrit la solution. La ligne

doNothing().when(cmd).dnsCheck(HOST, any(InetAddressFactory.class))

utilise une valeur brute et une correspondance, lorsqu'il est nécessaire d'utiliser toutes les valeurs brutes ou toutes les correspondances. Une version correcte peut lire

doNothing().when(cmd).dnsCheck(eq(HOST), any(InetAddressFactory.class))
Ryan Stewart
la source
8
Comme c'est idiot de ma part. J'ai continué à analyser pourquoi le 2ème paramètre continuait à me donner l'erreur. Merci de clarifier. Je suis très nouveau à Mockito, c'est ma première rencontre.
devang
32

J'ai eu le même problème depuis longtemps maintenant, j'avais souvent besoin de mélanger Matchers et valeurs et je n'ai jamais réussi à faire ça avec Mockito .... jusqu'à récemment! J'ai mis la solution ici en espérant qu'elle aidera quelqu'un même si ce post est assez ancien.

Il n'est clairement pas possible d'utiliser les Matchers AND ensemble dans Mockito, mais que se passe-t-il s'il y avait un Matcher acceptant de comparer une variable? Cela résoudrait le problème ... et en fait il y a: eq

when(recommendedAccessor.searchRecommendedHolidaysProduct(eq(metas), any(List.class), any(HotelsBoardBasisType.class), any(Config.class)))
            .thenReturn(recommendedResults);

Dans cet exemple, «metas» est une liste de valeurs existante

sam
la source
5
Impressionnant. org.mockito.Mockito.eq()
javaPlease42
4
l'importation appropriée est maintenant org.mockito.ArgumentMatchers.eq ()
sam
15

Cela pourrait aider quelqu'un à l'avenir: Mockito ne prend pas en charge la moquerie des méthodes `` finales '' (pour le moment). Cela m'a donné la même chose InvalidUseOfMatchersException.

La solution pour moi était de mettre la partie de la méthode qui n'avait pas besoin d'être «finale» dans une méthode séparée, accessible et remplaçable.

Passez en revue l' API Mockito pour votre cas d'utilisation.

delucasvb
la source
Cela a aidé à comprendre pourquoi mon code kotlin me donnerait une erreur, car toutes les méthodes de kotlin sont définitives!
sorry_I_wont
0

Malgré l'utilisation de tous les matchers, j'obtenais le même problème:

"org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Invalid use of argument matchers!
1 matchers expected, 3 recorded:"

Il m'a fallu peu de temps pour comprendre que la méthode que j'essayais de me moquer était une méthode statique d'une classe (disons Xyz.class) qui ne contient qu'une méthode statique et j'ai oublié d'écrire la ligne suivante:

PowerMockito.mockStatic(Xyz.class);

Peut-être que cela aidera les autres, car cela peut également être la cause du problème.

S Kumar
la source
0

Pour mon cas, l'exception a été soulevée parce que j'ai essayé de se moquer d'une package-accessméthode. Lorsque j'ai changé le niveau d'accès à la méthode de packageà protectedl'exception a disparu. Par exemple à l'intérieur sous la classe Java,

public class Foo {
    String getName(String id) {
        return mMap.get(id);
    }
}

la méthode String getName(String id)doit être AU MOINS au protected niveau pour que le mécanisme de moquerie (sous-classification) puisse fonctionner.

Shizhen
la source