Necesito escribir pruebas JUnit para una aplicación antigua que está mal diseñada y está escribiendo muchos mensajes de error en la salida estándar. Cuando el getResponse(String request)método se comporta correctamente, devuelve una respuesta XML:
@BeforeClass
public static void setUpClass() throws Exception {
Properties queries = loadPropertiesFile("requests.properties");
Properties responses = loadPropertiesFile("responses.properties");
instance = new ResponseGenerator(queries, responses);
}
@Test
public void testGetResponse() {
String request = "<some>request</some>";
String expResult = "<some>response</some>";
String result = instance.getResponse(request);
assertEquals(expResult, result);
}
Pero cuando obtiene un formato XML incorrecto o no comprende la solicitud, vuelve nully escribe algunas cosas en la salida estándar.
¿Hay alguna forma de afirmar la salida de la consola en JUnit? Para detectar casos como:
System.out.println("match found: " + strExpr);
System.out.println("xml not well formed: " + e.getMessage());

Respuestas:
utilizando ByteArrayOutputStream y System.setXXX es simple:
ejemplos de casos de prueba:
Usé este código para probar la opción de línea de comando (afirmando que -version genera la cadena de versión, etc., etc.)
Editar: versiones anteriores de esta respuesta llamadas
System.setOut(null)después de las pruebas; Esta es la causa de que los comentaristas NullPointerExceptions se refieren.fuente
NullPointerExceptionen otras pruebas después de configurar un flujo de error nulo como se sugirió anteriormente (enjava.io.writer(Object), llamado internamente por un validador XML). En su lugar, sugeriría guardar el original en un campo:oldStdErr = System.erry restaurar esto en el@Aftermétodo.Sé que este es un hilo viejo, pero hay una buena biblioteca para hacer esto:
Reglas del sistema
Ejemplo de los documentos:
También le permitirá atrapar
System.exit(-1)y otras cosas por las que una herramienta de línea de comando necesitaría ser probada.fuente
En lugar de redirigir
System.out, refactorizaría la clase que usaSystem.out.println()al pasar aPrintStreamcomo colaborador y luego usarSystem.outen producción y un Spy de prueba en la prueba. Es decir, use la inyección de dependencia para eliminar el uso directo de la secuencia de salida estándar.En producción
En la prueba
Discusión
De esta forma, la clase bajo prueba se vuelve comprobable mediante una simple refactorización, sin tener la necesidad de una redirección indirecta de la salida estándar o una intercepción oscura con una regla del sistema.
fuente
ConsoleWriteres el sujeto de prueba,Puede configurar el flujo de impresión System.out a través de setOut () (y para
inyerr). ¿Puede redirigir esto a una secuencia de impresión que grabe en una cadena y luego inspeccionar eso? Ese parecería ser el mecanismo más simple.(Yo recomendaría, en algún momento, convertir la aplicación en un marco de registro, ¡pero sospecho que ya lo sabe!)
fuente
Ligeramente fuera de tema, pero en caso de que algunas personas (como yo, cuando encontré este hilo por primera vez) pudieran estar interesadas en capturar la salida del registro a través de SLF4J, JUnit de commons-testing
@Rulepodría ayudar:Descargo de responsabilidad :
log4j,log4j2ylogbackestán disponibles en este momento, pero me complace agregar más.fuente
La respuesta de @dfa es excelente, así que di un paso más para hacer posible probar bloques de salida.
Primero creé
TestHelpercon un métodocaptureOutputque acepta la clase anónimaCaptureTest. El método captureOutput hace el trabajo de configurar y derribar las secuencias de salida. Cuando la ejecución deCaptureOutput'stestmétodo se llama, tiene acceso a la salida de generar para el bloque de prueba.Fuente de TestHelper:
Tenga en cuenta que TestHelper y CaptureTest se definen en el mismo archivo.
Luego, en su prueba, puede importar la captura estática de salida. Aquí hay un ejemplo usando JUnit:
fuente
Si estaba usando Spring Boot (mencionó que está trabajando con una aplicación antigua, por lo que probablemente no lo sea, pero podría ser útil para otros), entonces podría usar org.springframework.boot.test.rule.OutputCapture en la siguiente manera:
fuente
Basado en la respuesta de @ dfa y otra respuesta que muestra cómo probar System.in , me gustaría compartir mi solución para dar una entrada a un programa y probar su salida.
Como referencia, uso JUnit 4.12.
Digamos que tenemos este programa que simplemente replica la entrada a la salida:
Para probarlo, podemos usar la siguiente clase:
No explicaré mucho, porque creo que el código es legible y cité mis fuentes.
Cuando se ejecuta JUnit
testCase1(), llamará a los métodos de ayuda en el orden en que aparecen:setUpOutput(), debido a la@BeforeanotaciónprovideInput(String data), llamado desdetestCase1()getOutput(), llamado desdetestCase1()restoreSystemInputOutput(), debido a la@AfteranotaciónNo probé
System.errporque no lo necesitaba, pero debería ser fácil de implementar, similar a las pruebasSystem.out.fuente
No desea redirigir la secuencia system.out porque eso redirige para TODA la JVM. Cualquier otra cosa que se ejecute en la JVM puede estropearse. Hay mejores formas de probar la entrada / salida. Mira en trozos / simulacros.
fuente
Ejemplo completo de JUnit 5 para probar
System.out(reemplace la parte when):fuente
No puede imprimir directamente utilizando system.out.println o utilizando la api del registrador mientras utiliza JUnit . Pero si desea verificar cualquier valor, simplemente puede usar
Lanzará el siguiente error de aserción:
Su valor debe ser 21.92. Ahora, si va a realizar la prueba con este valor, como se muestra a continuación, su caso de prueba pasará.
fuente
para salir
por err
fuente
@Rule, en lugar de hacerlo en línea en su prueba. Notablemente, si su afirmación fallaSystem.setOut/Err, no se alcanzará la segunda llamada .