2010-04-02 21 views
17

Tengo un fragmento de código que lee datos de un archivo. Quiero forzar IOException en este código para fines de prueba (quiero comprobar si el código arroja una excepción personalizada correcta en este caso).Force IOException durante la lectura de archivos

¿Hay alguna manera de crear un archivo que esté protegido de la lectura, por ejemplo? Tal vez lidiar con algunos controles de seguridad puede ayudar?

Tenga en cuenta que pasar el nombre de un archivo inexistente no puede ayudar, porque FileNotFoundException tiene una cláusula de catch por separado.

Aquí está la pieza de código para una mejor comprensión de la pregunta:

BufferedReader reader = null; 
    try { 

     reader = new BufferedReader(new FileReader(csvFile)); 

     String rawLine; 
     while ((rawLine = reader.readLine()) != null) { 
      // some work is done here 
     } 

    } catch (FileNotFoundException e) { 
     throw new SomeCustomException(); 
    } catch (IOException e) { 
     throw new SomeCustomException(); 
    } finally { 
     // close the input stream 
     if (reader != null) { 
      try { 
       reader.close(); 
      } catch (IOException e) { 
       // ignore 
      } 
     } 
    } 
+0

Usted puede intentar leer un archivo que no está autorizado a leer. En Linux '/ proc/kcore' es una buena apuesta, como lo es'/etc/shadow'. –

+1

no es una respuesta, sino una observación. Debería envolver la IOException con su excepción personalizada para conservar el seguimiento completo de la pila. es decir, 'lanzar nueva SomeCusomException (e)' –

Respuesta

-1

Siempre se puede lanzar su propia IOException:

throw new IOException("Test IOException"); 
+0

Agregué el código para la pregunta original. Parece que no lo entendiste. – DixonD

0

Se podría hacer esta excepción a recaudar para un archivo que es demasiado grande.

2

Puede intentar crear el archivo como superusuario y luego leerlo como un usuario estándar. Debería haber problemas de permisos allí. O simplemente cambia la cosa asumiendo que estás en Linux. También puede intentar colocarlo en un directorio oculto/protegido.

+0

¿Puede proporcionar un ejemplo que funcione en cualquier sistema operativo de destino? – DixonD

+3

Dado que los sistemas operativos difieren bastante drásticamente en términos de lo que hacen con sus sistemas de archivos y administración de usuarios, es difícil. Puedes intentar usar un objeto de archivo java y llamar a setReadable/setWritable en él - ver http://java.sun.com/javase/6/docs/api/java/io/File.html#setReadable%28boolean%29 –

+1

Increíblemente respuesta inteligente. Incluso es multiplataforma. No requiere un marco de burla de terceros. Debería ser la respuesta aceptada si me preguntas. – jontejj

4

Si puede refactorizar ligeramente el código para aceptar un Reader, en lugar de un nombre de archivo, puede usar mocks. Con EasyMock puede crear un lector de prueba y configurarlo para lanzar IOException al llamar a cualquiera de sus métodos que desee. A continuación, sólo tiene que pasar al método a ensayar, y ver lo que sucede :-)

void readFile(Reader reader) throws SomeCustomException { 
    try { 
     String rawLine; 
     while ((rawLine = reader.readLine()) != null) { 
      // some work is done here 
     } 

    } catch (FileNotFoundException e) { 
     throw new SomeCustomException(); 
    } catch (IOException e) { 
     throw new SomeCustomException(); 
    } finally { 
     // close the input stream 
     if (reader != null) { 
      try { 
       reader.close(); 
      } catch (IOException e) { 
       // ignore 
      } 
     } 
    } 
} 

entonces el código de prueba:

mockReader = createMock(Reader.class); 
expect(mockReader.readLine()).andThrow(
     new IOException("Something terrible happened")); 
replay(mockReader); 

objectToTest.readFile(reader); 
+0

Es una pena que no pueda cambiar el código probado – DixonD

+1

@DixonD: si no puede cambiarlo, y no está diseñado correctamente, no puede realizar la prueba unitaria. Lo mejor que puedes esperar es hacer algunas pruebas de integración. –

1

Se puede utilizar una biblioteca Mock como Mockito o Easymock (+classpath) para crear un objeto de archivo Mock (las libs más nuevas tienen extensiones de cargador de clases que le permiten simular clases concretas como File), o pueden cooperar con algo como PowerMock (see blog) y tener un simulacro generado para la llamada del constructor y arrojar la excepción apropiada cuando se llama.

+0

No hay forma de pasar el simulacro en el código – DixonD

+0

Editado la respuesta para vincular a una entrada de blog sobre el uso de PowerMock para este tipo de prueba (aprovecha la manipulación de ClassLoader) – jayshao

7

Descargo de responsabilidad: No he probado esto en una plataforma que no sea de Windows, por lo que puede tener diferentes resultados en una plataforma con diferentes características de bloqueo de archivos.

Si bloquea el archivo de antemano, puede desencadenar una IOException cuando algo intenta leer de él:

java.io.IOException: The process cannot access the file because another process has locked a portion of the file 

Esto funciona incluso si se encuentra en el mismo hilo.

He aquí algunos ejemplos de código:

final RandomAccessFile raFile = new RandomAccessFile(csvFile, "rw"); 
raFile.getChannel().lock(); 
+2

No funciona para mí, utilizando Ubuntu ... pero la idea es bueno :) –

+0

funciona en Windows – panny

1

Se podría forzar una excepción al invocar el método de cerca en su BufferedReader:

reader = new BufferedReader(new FileReader(csvFile)); 

    // invoke the Close() method. 
    reader.Close(); 

    String rawLine; 
    while ((rawLine = reader.readLine()) != null) { 
     // some work is done here 
    } 

Espero que ayude.

0

No recomendaría usar FileNotFoundException. Si desea lanzar una excepción específica para el archivo que no existe, comprobaría csvFile.exists().

Por ejemplo, puede hacer csvFile un directorio. Probé su código y se tiró:

File file = new File("actually_a_directory.csv"); file.mkdir(); yourCode(file); // throws FileNotFoundException: "actually_a_directory.csv (Access is denied)"

En mi opinión, un archivo de ser en realidad un directorio no es lo mismo que FileNotFound, sin embargo, actúa de la misma en Java.

0

de definir en su prueba de un FileInputStream sobrecargado que se produce una excepción

FileInputStream s; 
try { 
    s = new FileInputStream(fileName) { 

      @Override 
      public int read() throws IOException { 
       throw new IOException("Expected as a test"); 
      } 
     }; 
} catch (FileNotFoundException e) { 
    throw new RuntimeException(e.getMessage(), e); 
} 
Cuestiones relacionadas