¿Cómo verificar que no se haya llamado a un método específico usando Mockito?

627

¿Cómo verificar que un método no se invoque en la dependencia de un objeto?

Por ejemplo:

public interface Dependency {
    void someMethod();
}

public class Foo {
    public bar(final Dependency d) {
        ...
    }
}

Con la prueba de Foo:

public class FooTest {
    @Test
    public void dependencyIsNotCalled() {
        final Foo foo = new Foo(...);
        final Dependency dependency = mock(Dependency.class);
        foo.bar(dependency);
        **// verify here that someMethod was not called??**
    }
}
beluchin
fuente

Respuestas:

1090

Aún más significativo:

import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;

// ...

verify(dependency, never()).someMethod();

La documentación de esta función está en §4 "Verificación del número exacto de invocaciones / al menos x / nunca" , y el neverjavadoc está aquí .

Brice
fuente
144
Usar neveres la forma mejor y más específica, pero si necesita verificar un objeto simulado completo, también considere verifyZeroInteractions(mockObject)o verifyNoMoreInteractions(mockObject).
Jeff Bowman
¿Qué hacer si someMethod es privado?
Sumit Kumar Saha
1
Entonces no puedes burlarte en primer lugar (con Mockito);) PowerMock lo permite, pero es más complejo de configurar. O si tiene la propiedad del código, relaja la visibilidad del paquete.
Brice
2
Desde 3.0.1 verifyZeroInteractionsha quedado en desuso. verifyNoInteractions Es la alternativa sugerida. La versión de Mockito en el momento de este comentario es 3.3.3
VKB
109

use el segundo argumento sobre el Mockito.verifymétodo, como en:

verify(dependency, Mockito.times(0)).someMethod()

beluchin
fuente
11
Public static VerificationMode never () {tiempos de retorno (0); }
gbero
3
never()no es significativamente más legible que times(0). Pero la existencia de neversí aumenta la carga cognitiva y hace que el sistema mockito sea más difícil de entender y recordar cómo usarlo. Así que realmente mockito no debería haber incluido neveren su API, no vale la pena el costo mental.
BT
Pregunta: ¿este formulario verifica que someMethodse llamó 0 veces, o solo verifica que someMethodnunca se llamó con cero argumentos?
BT
@BT: me imagino que verifica que someMethodcon cero argumentos se llamó cero veces, no verificado.
beluchin
18

Como un patrón más general a seguir, tiendo a usar un @Afterbloque en la prueba:

@After
public void after() {
    verifyNoMoreInteractions(<your mock1>, <your mock2>...);
}

Entonces la prueba es libre de verificar solo lo que debería llamarse.

Además, descubrí que a menudo me olvidaba de verificar "no interacciones", solo para descubrir más tarde que se llamaban cosas que no deberían haber sido.

Por lo tanto, considero que este patrón es útil para capturar todas las llamadas inesperadas que no se han verificado específicamente.

David Lavender
fuente
99
La documentación de Mockito establece que no se debe abusar de este patrón: "Una palabra de advertencia: algunos usuarios que hicieron muchas burlas clásicas de esperar-ejecutar-verificar tienden a usar verifiqueNoMoreInteractions () muy a menudo, incluso en todos los métodos de prueba. GenerateNoMoreInteractions () no se recomienda su uso en todos los métodos de prueba. verificarNoMoreInteractions () es una afirmación útil del conjunto de herramientas de prueba de interacción. Úselo solo cuando sea relevante. Abusar de él conduce a pruebas demasiado especificadas y menos mantenibles ". Ver aquí
Chadi
2
"Úselo solo cuando sea relevante". Siento que siempre es relevante. No veo ese patrón como abuso: como dije, descubre que "se estaban llamando cosas que no deberían haber sido". Para mí, esa es una pieza vital de verificación: si algo llama a un repositorio que no debería estar usando, ¡quiero saberlo! ¿A menos que haya otra forma de verificar eso sin usar verifyNoMoreInteractions? Las otras respuestas aquí se basan en que el escritor de la prueba recuerda explícitamente enumerar estas comprobaciones: eso es demasiado propenso a errores en mi libro.
David Lavender
2
Vi este comentario, pero también sentí que el razonamiento no era convincente. Me encantaría leer más sobre por qué esto no se recomienda.
tobinibot
2
@tobinibot Porque la idea de las pruebas unitarias es verificar un Contrato. La mayoría de los contratos generalmente no implican cuántas veces se invoca algún otro método, sino que pasar parámetros conocidos da como resultado una respuesta conocida. Al no usar más interacciones, básicamente está verificando la implementación línea por línea, lo que hace que la refactorización y la implementación sean tediosas. Cuál no es el punto de la prueba unitaria.
Andrew T Finnell
8

En primer lugar: siempre debe importar mockito static, de esta manera el código será mucho más legible (e intuitivo):

import static org.mockito.Mockito.*;

En realidad, hay muchas maneras de lograr esto, sin embargo, es (posiblemente) más limpio usar el

verify(yourMock, times(0)).someMethod();

método en todas sus pruebas, cuando en otras pruebas lo usa para afirmar una cierta cantidad de ejecuciones como esta:

verify(yourMock, times(5)).someMethod();

Las alternativas son:

verify(yourMock, never()).someMethod();

Alternativamente, cuando realmente desea asegurarse de que cierto Objeto burlado en realidad NO se llame en absoluto, puede usar:

verifyZeroInteractions(yourMock)
fl0w
fuente
7

Tanto el verifyNoMoreInteractions()y verifyZeroInteractions()método tiene internamente la misma aplicación como:

public static transient void verifyNoMoreInteractions(Object mocks[])
{
    MOCKITO_CORE.verifyNoMoreInteractions(mocks);
}

public static transient void verifyZeroInteractions(Object mocks[])
{
    MOCKITO_CORE.verifyNoMoreInteractions(mocks);
}

para que podamos usar cualquiera de ellos en un objeto simulado o una matriz de objetos simulados para verificar que no se haya llamado a ningún método utilizando objetos simulados.

Ujjwal
fuente