2010-01-30 15 views
24

Estoy escribiendo pruebas de integración usando JUnit para automatizar la prueba de una aplicación basada en consola. La aplicación es tarea pero esta parte no es la tarea. Quiero automatizar estas pruebas para ser más productivo. No quiero tener que volver atrás y volver a probar las partes ya probadas de la aplicación. (Razones estándar para usar las pruebas unitarias)Java, Junit - Capture la entrada/salida estándar para usar en una prueba de unidad

De todos modos, no puedo entender ni encontrar un artículo sobre la captura de la salida para poder hacer assertEquals ni proporcionar entrada automatizada. No me importa si la salida/entrada va al panel de la consola/salida. Solo necesito que la prueba se ejecute y verifique que la salida es la esperada dada la entrada.

Cualquiera tiene un artículo o código para ayudar con esto.

+0

@dfa, no estoy de acuerdo. Es similar pero lo suficientemente diferente. –

+0

... concedida la respuesta es la misma ... –

+1

El otro hilo ahora tiene una mejor respuesta. Implica el uso de la regla del sistema jUnit StandardOutputStreamLog. También hay reglas del sistema para stderr y stdin. –

Respuesta

38

Utilice System.setOut() (y System.setErr()) para redirigir la salida a una gama de impresiones arbitraria, que puede ser una que lea programáticamente.

Por ejemplo:

final ByteArrayOutputStream myOut = new ByteArrayOutputStream(); 
System.setOut(new PrintStream(myOut)); 

// test stuff here... 

final String standardOutput = myOut.toString(); 
+1

Así que simplemente 'PrintStream _out = System.out;' ¿No funcionará? –

+0

Sería, es decir, tendría una referencia al flujo de salida existente, pero no puede * leer * nada de él, ya que no existen métodos apropiados para hacerlo en la interfaz general de 'PrintStream'. La técnica consiste en configurar la salida a un flujo de impresión específico que sepa cómo leer. –

7

La clase System tiene métodos setIn(), setOut() y setErr() que le permiten establecer las corrientes de entrada, salida y de error estándar, por ejemplo, a ByteArrayOutputStream que puede inspeccionar a voluntad.

1

Aquí está la solución en lugar de ByteArrayOutputStream. No agrega nada a la idea de System.setOut. Más bien, quiero compartir la implementación que es mejor que capturar todo en ByteArrayOutputStream. Prefiero capturar solo la información seleccionada y dejar que todos los mensajes de registro aparezcan en la consola a medida que se registran en lugar de capturar todo en un portada (¿de qué tamaño?) Para su posterior procesamiento.

/** 
* Once started, std output is redirected to this thread. 
* Thread redirects all data to the former system.out and 
* captures some strings.*/ 
static abstract class OutputCaputre extends Thread { 

    // overrdie these methods for System.err 
    PrintStream getDownstream() { return System.out;} 
    void restoreDownstream() { System.setOut(downstream);} 

    // will be called for every line in the log 
    protected abstract void userFilter(String line); 

    final PrintStream downstream; 
    public final PipedInputStream pis; 
    private final PipedOutputStream pos; 
    OutputCaputre() throws IOException { 
     downstream = getDownstream(); 

     pos = new PipedOutputStream(); 
     pis = new PipedInputStream(pos); 
     System.setOut(new PrintStream(pos)); 

     start(); 
    } 

    public void run() { 
     try { 
      BufferedReader br = new BufferedReader(new InputStreamReader(pis)); 

      // once output is resotred, we must terminate 
      while (true) { 
       String line = br.readLine(); 
       if (line == null) { 
        return; 
       } 
       downstream.println(line); 
       userFilter(line); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public void terminate() throws InterruptedException, IOException { 
     restoreDownstream(); // switch back to std 
     pos.close(); // there will be no more data - signal that 
     join(); // and wait until capture completes 
    } 
}; 

Aquí se muestra un ejemplo de la utilización de la clase:

OutputCaputre outputCapture = new OutputCaputre() { 
    protected void userFilter(String line) { 
     downstream.println("Capture: " + line); 
    }  
}; 
System.out.println("do you see me captured?"); 
// here is your test  
outputCapture.terminate(); // finally, stop capturing 
Cuestiones relacionadas