Usando el método genérico "any ()" de Mockito

194

Tengo una interfaz con un método que espera una matriz de Foo:

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

Me estoy burlando de esta interfaz usando Mockito, y me gustaría afirmar que doStuff()se llama, pero no quiero validar qué argumento se pasa - "no me importa".

¿Cómo escribo el siguiente código usando any(), el método genérico, en lugar de anyObject()?

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

Respuestas:

111

Desde Java 8 puede usar el anymétodo sin argumentos y el compilador inferirá el argumento de tipo:

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

Explicación

Lo nuevo en Java 8 es que el tipo de destino de una expresión se usará para inferir los parámetros de tipo de sus subexpresiones. Antes de Java 8, solo los argumentos de los métodos se usaban para la inferencia de parámetros de tipo (la mayoría de las veces).

En este caso, el tipo de parámetro de doStuffserá el tipo de destino para any(), y el tipo de valor de retorno de any()será elegido para que coincida con ese tipo de argumento.

Este mecanismo se agregó en Java 8 principalmente para poder compilar expresiones lambda, pero en general mejora las inferencias de tipos.


Tipos primitivos

Esto no funciona con tipos primitivos, desafortunadamente:

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

El problema es que el compilador inferirá Integercomo el valor de retorno de any(). Mockito no se dará cuenta de esto (debido a la eliminación de tipo) y devolverá el valor predeterminado para los tipos de referencia, que es null. El tiempo de ejecución intentará desempaquetar el valor de retorno llamando al intValuemétodo antes de pasarlo doStuff, y se genera la excepción.

Lii
fuente
¡Estoy gratamente sorprendido cada vez que esta respuesta recibe un voto positivo! Habría adivinado que la pregunta no llamaría mucho la atención desde Java 8, ya que el anymétodo debería funcionar. ¡No buscas respuestas para cosas que simplemente funcionan!
Lii
Vine aquí porque no sabía por qué mi código no funcionaba any()pero estaba bien anyBoolean(), lo que la última parte de su respuesta arroja luz hermosamente.
AdrienW
274

Esto debería funcionar

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

verify(bar).DoStuff(any(Foo[].class));
estar nervioso
fuente
31
en caso de que alguien lo necesite en Scala:verify(bar).DoStuff(any[Array[Foo]])
tolitius
66
Tuve un problema con la importación, estaba usando any () de hamcrest en mis importaciones y chocó con el de mockito.
Doppelganger
44
Eche un vistazo a la API, el argumento de clase solo se usa para emitir, ¡el método aún acepta cualquier tipo de objeto! site.mockito.org/mockito/docs/current/org/mockito/… . Use isA () para este caso site.mockito.org/mockito/docs/current/org/mockito/… .
thilko
1
Esta clase ahora está en desuso para evitar un choque de nombres con Hamcrest. Use org.mockito.ArgumentMatchers
leo9r
12

Puedes usar Mockito.isA()para eso:

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
fuente
Esta es la respuesta correcta. Usar any (Clazz) está completamente mal.
Surasin Tancharoen
3
@SurasinTancharoen En realidad, cualquier (Clase) es solo un alias de isA (Clase) (ver los documentos). Entonces no está del todo mal.
jmiserez
8

Como necesitaba usar esta función para mi último proyecto (en un momento lo actualizamos desde el 1.10.19), solo para mantener actualizados a los usuarios (que ya usan la versión 2.1.0 o superior de mockito-core ), la estática Los métodos de las respuestas anteriores deben tomarse de la ArgumentMatchersclase:

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

Tenga esto en cuenta si planea mantener sus artefactos Mockito actualizados, ya que posiblemente a partir de la versión 3, es posible que esta clase ya no exista:

Según 2.1.0 y superior, Javadoc de org.mockito.Matchers establece:

Uso org.mockito.ArgumentMatchers. Esta clase ahora está en desuso para evitar un choque de nombres con la org.hamcrest.Matchers clase Hamcrest * . Es probable que esta clase se elimine en la versión 3.0.

He escrito un pequeño artículo sobre comodines de mockito si está listo para leer más.

Maciej Kowalski
fuente
¿Cómo puedo importar org.mockito.ArgumentMatcher en Scala? Intenté importar org.mockito.ArgumentMatcher.any obtengo el error `value any no es miembro del objeto org.mockito.ArgumentMatcher
Manu Chadha
¿Podría decirme cuál es el equivalente en la versión 3.0?
Manu Chadha
Lo sabremos una vez que sea lanzado;)
Maciej Kowalski