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 null
y 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
NullPointerException
en 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.err
y restaurar esto en el@After
mé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 aPrintStream
como colaborador y luego usarSystem.out
en 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
ConsoleWriter
es el sujeto de prueba,Puede configurar el flujo de impresión System.out a través de setOut () (y para
in
yerr
). ¿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
@Rule
podría ayudar:Descargo de responsabilidad :
log4j
,log4j2
ylogback
está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é
TestHelper
con un métodocaptureOutput
que 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
'stest
mé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@Before
anotaciónprovideInput(String data)
, llamado desdetestCase1()
getOutput()
, llamado desdetestCase1()
restoreSystemInputOutput()
, debido a la@After
anotaciónNo probé
System.err
porque 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 .