Pregunta

Estoy escribiendo una prueba para un fragmento de código que tiene una captura de IOException que estoy tratando de cubrir. El try / catch se ve algo como esto:

try {
    oos = new ObjectOutputStream(new FileOutputStream(cacheFileName));
} catch (IOException e) {
    LOGGER.error("Bad news!", e);
} finally {

La forma más fácil parece hacer que FileOutputStream arroje una excepción FileNotFoundException, pero tal vez estoy haciendo esto de la manera incorrecta.

¿Alguien por ahí tiene algún consejo?

¿Fue útil?

Solución

De tu comentario:

  

Sí, supongo que la pregunta debería   Realmente he sido " ¿Cómo creo un   archivo que no existe tanto en Linux   y Windows? " En las ventanas, puedo usar   'Nuevo archivo (" X: / ")', donde X: es una unidad   Carta que no existe. En Linux,   Esto no funciona porque eso es una   nombre de archivo válido.

Mira java.io.File.createTempFile. Úsalo para crear el archivo y luego elimínalo.

Probablemente páselo como:

File tempFile;

tempFile = createTempFile(getClass().getName(), 
                          Long.toString(System.currentTimeMillis());
tempFile.delete();

Eso debería darle un nombre único de manera indendente a la plataforma que pueda usar de manera segura sin (mucho) temor a que exista.

Otros consejos

Puede establecer cacheFileName en un nombre no válido o en uno que sepa que no existe.

Hay dos partes en cualquier prueba: lograr que suceda y medir que obtuvo el resultado correcto.

Inyección de falla

La respuesta más fácil es la que ya se ha mencionado, que es establecer cacheFileName en un archivo que nunca existirá. Esta es probablemente la respuesta más práctica en esta situación.

Sin embargo, para provocar una condición arbitraria como una IOException , lo que realmente desea es Inyección de falla . Esto fuerza fallas en su código sin obligarlo a instrumentar su código fuente. Aquí hay algunos métodos para hacer esto:

  • Objetos simulados Puede usar un método de fábrica para crear un ObjectOutputStream o FileOutputStream invalidado. En el código de prueba, la implementación arrojaría una IOException cuando lo deseara, y en el código de producción no modificaría el comportamiento normal.
  • Inyección de dependencia Para colocar su objeto simulado en el lugar correcto, puede usar un marco como Spring o Seamos para " inyectar " el objeto apropiado en la clase que está haciendo el trabajo. Puede ver que estos marcos incluso tienen prioridad para los objetos que se inyectarán, de modo que durante la prueba de la unidad puede anular los objetos de producción con objetos de prueba.
  • Programación orientada a aspectos En lugar de cambiar la estructura De su código, puede usar AOP para inyectar la falla en el lugar correcto. Por ejemplo, utilizando AspectJ puede definir un Pointcut a donde quiere que se lance la excepción, y tiene el Advice lanza la excepción deseada.

Hay otras respuestas a la inyección de fallas en Java; por ejemplo, un producto llamado AProbe fue pionero en lo que podría llamarse AOP en C hace mucho tiempo, y también tener un producto Java.

Validación

Obtener la excepción es un buen comienzo, pero también debe validar que obtuvo el resultado correcto. Suponiendo que el ejemplo de código que tiene allí sea correcto, desea validar que registró esa excepción. Alguien mencionado anteriormente utiliza un objeto simulado para su registrador, que es una opción viable. También puede utilizar AOP aquí para capturar la llamada al registrador.

Supongo que el registrador es log4j ; para resolver un problema similar, implementé mi propio log4j appender que captura la salida de log4j: capturo específicamente solo ERROR y FATAL , que probablemente sean los mensajes de registro interesantes en tales un caso. Se hace referencia al apéndice en log4j.xml y se activa durante la ejecución de la prueba para capturar la salida del registro de errores. Esto es esencialmente un objeto simulado, pero no tuve que reestructurar todo mi código que obtuvo un log4j Logger .

  

Estoy escribiendo una prueba para un fragmento de código   que tiene una captura IOException en ella   que estoy tratando de cubrir.

No estoy completamente seguro de entender su objetivo, pero si desea probar si se produce la excepción, puede indicar a la prueba que espera que arroje la excepción:

@Test(expected=IOException.class)

Su prueba fallará si no se lanza la excepción y tendrá éxito si se lanza (por ejemplo, si el archivo cacheFileName no existe).

Una excepción FileNotFoundException obviamente activará la captura. El javadoc establece los casos en los que se lanzará.

También debe considerar que el constructor ObjectOutputStream puede lanzar una excepción IOException, por lo que puede querer cubrir este caso en sus pruebas.

Dos maneras fáciles serían establecer cacheFileName en un archivo inexistente o establecer el archivo especificado para acceso de solo lectura.

-John

Como el código está escrito actualmente, puede intentar simular la llamada de error () en el objeto LOGGER y verificar si se llama cuando espera una IOException.

Tu deseo de probar puede haber descubierto un problema fundamental con el código tal como está escrito. Se está produciendo un error, pero no hay un valor booleano o de marca (establezca el nombre de archivo en un patrón especial) que proporcione otras secciones de código para determinar si la escritura en el archivo fue exitosa. Si esto está contenido en una función, tal vez podría devolver un valor booleano o establecer una variable de nivel de objeto.

cacheFileName = "thisFileShouldNeverExistAndIfItDoesYouAreScrewingUpMyTests";

Claro que puedes tomar medidas y saltar a través de aros para asegurarte de que el nombre del archivo nunca existirá jamás, o puedes usar una cadena que nunca existirá en el 99.99999% de los casos.

Espero que esto sea lo que quisiste decir.

if(new File(cachedFile).exists()) {
    oos = new ObjectOutputStream(new FileOutputStream(cacheFileName));
    //do your code here
} else {
    throw new FileNotFoundException("File doesn't exist!");
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top