Utilisation de la méthode générique «any ()» de Mockito

194

J'ai une interface avec une méthode qui attend un tableau de Foo:

public interface IBar {
  void doStuff(Foo[] arr);
}

Je me moque de cette interface en utilisant Mockito, et je voudrais affirmer que cela doStuff()s'appelle, mais je ne veux pas valider quel argument est passé - "ne se soucie pas".

Comment puis-je écrire le code suivant à l'aide de any()la méthode générique au lieu de anyObject()?

IBar bar = mock(IBar.class);
...
verify(bar).doStuff((Foo[]) anyObject());
ripper234
la source

Réponses:

111

Depuis Java 8, vous pouvez utiliser la anyméthode sans argument et l'argument type sera déduit par le compilateur:

verify(bar).doStuff(any());

Explication

La nouveauté de Java 8 est que le type cible d'une expression sera utilisé pour déduire les paramètres de type de ses sous-expressions. Avant Java 8, seuls les arguments des méthodes étaient utilisés pour l'inférence de paramètres de type (la plupart du temps).

Dans ce cas, le type de paramètre doStuffsera le type cible de any(), et le type de valeur de retour any()sera choisi pour correspondre à ce type d'argument.

Ce mécanisme a été ajouté dans Java 8 principalement pour pouvoir compiler des expressions lambda, mais il améliore généralement les inférences de type.


Types primitifs

Cela ne fonctionne pas avec les types primitifs, malheureusement:

public interface IBar {
    void doPrimitiveStuff(int i);
}

verify(bar).doPrimitiveStuff(any()); // Compiles but throws NullPointerException
verify(bar).doPrimitiveStuff(anyInt()); // This is what you have to do instead

Le problème est que le compilateur déduira Integerla valeur de retour de any(). Mockito n'en sera pas conscient (en raison de l'effacement des types) et renverra la valeur par défaut pour les types de référence, qui est null. Le runtime tentera de décompresser la valeur de retour en appelant la intValueméthode dessus avant de la passer à doStuff, et l'exception sera levée.

Lii
la source
Je suis agréablement surpris à chaque fois que cette réponse obtient un vote positif! J'aurais deviné que la question n'attirerait pas beaucoup l'attention depuis Java 8, car la anyméthode devrait simplement fonctionner. Vous ne cherchez pas de réponse pour des choses qui fonctionnent!
Lii
Je suis venu ici parce que je ne savais pas pourquoi mon code ne fonctionnait pas, any()mais que ça allait anyBoolean(), ce que la dernière partie de votre réponse éclaire magnifiquement.
AdrienW
274

Cela devrait fonctionner

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;

verify(bar).DoStuff(any(Foo[].class));
gigue
la source
31
juste au cas où quelqu'un en aurait besoin à Scala:verify(bar).DoStuff(any[Array[Foo]])
tolitius
6
J'ai eu un problème avec l'importation, j'utilisais le any () de hamcrest dans mes importations et il est entré en collision avec celui de mockito.
Doppelganger
4
Veuillez jeter un œil à l'API, l'argument de classe est juste utilisé pour le cast, la méthode accepte toujours tout type d'objet! site.mockito.org/mockito/docs/current/org/mockito/… . Utilisez isA () pour ce cas site.mockito.org/mockito/docs/current/org/mockito/… .
thilko
1
Cette classe est désormais déconseillée afin d'éviter un conflit de noms avec Hamcrest. Utilisez org.mockito.ArgumentMatchers
leo9r
12

Vous pouvez utiliser Mockito.isA()pour cela:

import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.verify;

verify(bar).doStuff(isA(Foo[].class));

http://site.mockito.org/mockito/docs/current/org/mockito/Matchers.html#isA(java.lang.Class)

thilko
la source
Ceci est la bonne réponse. Utiliser n'importe quel (Clazz) est complètement faux.
Surasin Tancharoen
3
@SurasinTancharoen En fait, n'importe quelle (classe) n'est qu'un alias de isA (classe) (voir la documentation). Ce n'est donc pas du tout faux.
jmiserez
8

Comme j'avais besoin d'utiliser cette fonctionnalité pour mon dernier projet (à un moment donné, nous avons mis à jour à partir de 1.10.19), juste pour tenir à jour les utilisateurs (qui utilisent déjà la version 2.1.0 ou supérieure de mockito-core ), le statique les méthodes des réponses ci-dessus doivent être prises en ArgumentMatchersclasse:

import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.ArgumentMatchers.any;

Veuillez garder cela à l'esprit si vous prévoyez de garder vos artefacts Mockito à jour car éventuellement à partir de la version 3, cette classe peut ne plus exister:

Selon 2.1.0 et supérieur, Javadoc de org.mockito.Matchers déclare:

Utilisez org.mockito.ArgumentMatchers. Cette classe est désormais obsolète afin d'éviter un conflit de noms avec la org.hamcrest.Matchers classe Hamcrest * . Cette classe sera probablement supprimée dans la version 3.0.

J'ai écrit un petit article sur les jokers mockito si vous souhaitez en savoir plus.

Maciej Kowalski
la source
Comment importer org.mockito.ArgumentMatcher dans Scala? J'ai essayé d'importer org.mockito.ArgumentMatcher.any J'obtiens l'erreur `value any n'est pas membre de l'objet org.mockito.ArgumentMatcher
Manu Chadha
Pourriez-vous me dire quel est l'équivalent dans la version 3.0?
Manu Chadha
Nous le saurons une fois qu'il sera sorti;)
Maciej Kowalski