2012-08-13 11 views
33

Estoy buscando una forma de verificar con Mockito, que no hubo interacción con un simulacro determinado durante una prueba. Es fácil lograr eso para un método dado con el modo de verificación never(), pero todavía no he encontrado una solución para el simulacro completo.Mockito: cómo verificar que nunca se invocó un simulacro

Lo que realmente quiero lograr: verificar en las pruebas, que nada se imprima en la consola. La idea general con jUnit va así:

private PrintStream systemOut; 

@Before 
public void setUp() { 
    // spy on System.out 
    systemOut = spy(System.out); 
} 

@After 
public void tearDown() { 
    verify(systemOut, never()); // <-- that doesn't work, just shows the intention 
} 

Un PrintStream tiene toneladas de métodos y realmente no quieren para verificar todos y cada uno por separado con verificar - y lo mismo para System.err ...

Así que espero, si hay una solución fácil, que puedo, dado que tengo una buena cobertura de prueba, forzar a los ingenieros de software (y a mí) a eliminar su (mi) código de depuración como System.out.println("Breakpoint#1"); o e.printStacktrace(); antes de confirmar los cambios.

Respuesta

37

Utilice esta:

import static org.mockito.Mockito.verifyZeroInteractions; 

// ... 

private PrintStream backup = System.out; 

@Before 
public void setUp() { 
    System.setOut(mock(PrintStream.class)); 
} 

@After 
public void tearDown() { 
    verifyZeroInteractions(System.out); 
    System.setOut(backup); 
} 
+0

Parece lo mejor que puedo hacer para este enfoque. ¡Gracias! (En realidad, he ocultado la mayor parte de la lógica en una clase auxiliar y también tuve que silenciar el registrador;)) –

6
verifyZeroInteractions(systemOut); 

Como se señala en los comentarios, esto no funciona con un espía.

Para una respuesta más o menos equivalente, pero más completa, vea la respuesta de gontard a esta pregunta.

+0

(facepalm) - pero no parece funcionar con el espionaje, tengo que burlarme de un PrintStream en su lugar y configurarlo en el sistema ... –

+0

Sin ver su código, supongo que la razón por la cual esto falla para su espías es que cuando cortas a tus espías, la llamada de método en el talón realmente cuenta como uno para ser verificado. Tres sugerencias (1) 'verifyNoMoreInvocations (ignoreStubs (mockOne, mockTwo));' - esto funcionará como 'verifyZeroInteractions', pero ignorará lo que ya has anulado. (2) ¿Está utilizando los métodos 'doReturn/doThrow/doAnswer' para configurar sus stubs? Por lo general, estos funcionan mejor que 'when' ...' thenReturn/thenThrow/then', cuando se trata de lidiar con espías. ... continúa –

+0

Sugerencia (3) es publicar un poco más de su código para que las personas aquí puedan ayudarlo mejor. –

4

usted podría intentar un rumbo ligeramente diferente:

private PrintStream stdout; 

@Before public void before() { 
    stdout = System.out; 
    OutputStream out = new OutputStream() { 
     @Override public void write(int arg0) throws IOException { 
      throw new RuntimeException("Not allowed"); 
     } 
    }; 
    System.setOut(new PrintStream(out)); 
} 

@After public void after() { 
    System.setOut(stdout); 
} 

Si se prefiere, se puede cambiar el tipo anónimo para una maqueta y verificar as Don Roby suggests.

+1

Definitivamente un +1. Desafortunadamente, esta vez me interesó una solución con Mockito, por lo tanto, aceptaré otra respuesta. Espero que no te moleste :) –

2

Una forma de resolver este problema es refactorizar la clase que se está probando, para permitir la inyección de un PrintStream que se puede utilizar para la salida. Esto le permitirá probarlo en una unidad, sin depender del comportamiento de la clase System. Puede usar un constructor privado de paquete para esta inyección, ya que solo lo usará de la clase de prueba correspondiente. Por lo tanto, podría verse algo como esto.

public class MyClass{ 
    private PrintWriter systemOut; 

    public MyClass(){ 
     this(System.out); 
    } 

    MyClass(PrintWriter systemOut){ 
     this.systemOut = systemOut; 

     // ...any other initialisation processing that you need to do 
    } 
} 

y dentro de la propia clase, utilizar la variable SystemOut en lugar de System.out donde se llama a este último.

Ahora, dentro de la clase de prueba, haga una simulación PrintStream y páselo al constructor privado del paquete para obtener el objeto que va a probar. Ahora puede ejecutar las acciones que desee de sus pruebas y usar verify para verificar sus efectos en su simulacro PrintStream.

+0

Ah, vale, pero no es exactamente lo que pretendía hacer: intenté encontrar una forma de probar una clase sin tocar esto, especialmente sin agregar código que solo se necesita para probar. Pero, por otro lado, si estamos dispuestos a preparar las clases bajo prueba, ¡este es un enfoque realmente agradable! –

Cuestiones relacionadas