2010-04-02 19 views
17

Ho un pezzo di codice che legge i dati da un file. Voglio forzare IOException in questo codice a scopo di test (voglio verificare se il codice genera un'eccezione personalizzata corretta in questo caso).Forza IOException durante la lettura del file

Esiste un modo per creare un file protetto da lettura, ad esempio? Forse affrontare alcuni controlli di sicurezza può aiutare?

Si prega di notare che passare il nome di un file inesistente non può essere d'aiuto, poiché FileNotFoundException ha una clausola catch separata.

Ecco il pezzo di codice per una migliore comprensione della questione:

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

Si può provare a leggere un file che non ti è permesso di leggere. Su Linux '/ proc/kcore' è una buona scommessa, come'/etc/shadow'. –

+1

non una risposta, ma un'osservazione. È necessario avvolgere IOException con l'eccezione personalizzata per conservare l'intera traccia dello stack. per esempio: lancio di nuova SomeCusomException (e) ' –

risposta

-1

Si può sempre buttare il proprio IOException:

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

Ho aggiunto il codice per la domanda originale. Sembra che tu non l'abbia capito. – DixonD

0

Si potrebbe fare questa eccezione alzare per un file che è troppo grande.

2

Si potrebbe provare a creare il file come superutente e quindi leggerlo come utente standard. Ci dovrebbero essere problemi di permessi lì. O semplicemente chmod la cosa assumendo che tu sia su Linux. Puoi anche provare a metterlo in una directory nascosta/protetta.

+0

Potete fornire un esempio che funzionerà su qualsiasi SO di destinazione? – DixonD

+3

Poiché i sistemi operativi differiscono abbastanza drasticamente in termini di ciò che fanno con i loro file system e la gestione degli utenti, è difficile. Puoi provare a utilizzare un oggetto File java e chiamare setReadable/setWritable su di esso - vedi http://java.sun.com/javase/6/docs/api/java/io/File.html#setReadable%28boolean%29 –

+1

Incredibilmente risposta intelligente È persino multipiattaforma. Non richiede una struttura di derisione di terze parti. Dovrebbe essere la risposta accettata se me lo chiedi. – jontejj

4

Se è possibile ridefinire leggermente il codice per accettare un Reader, anziché un nome file, è possibile utilizzare i mock. Con EasyMock puoi creare un lettore fittizio e impostarlo per lanciare IOException dopo aver chiamato uno dei suoi metodi che desideri. Poi basta passare al metodo da testare, e guardare cosa succede :-)

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 
      } 
     } 
    } 
} 

poi il codice di prova:

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

objectToTest.readFile(reader); 
+0

È un peccato non poter cambiare il codice testato – DixonD

+1

@DixonD: se non è possibile cambiarlo e non è progettato correttamente, non è possibile testarlo unitamente. Il meglio che puoi sperare è fare alcuni test di integrazione. –

1

È possibile utilizzare una libreria Mock come Mockito o Easymock (+classpath) per creare un oggetto file Mock (le nuove librerie hanno estensioni del classloader che ti permettono di prendere in giro classi concrete come File), o possono cooperare con qualcosa come PowerMock (see blog) e avere un mock generato per la chiamata del costruttore, e lanciare l'eccezione appropriata quando chiamato.

+0

Non è possibile passare la simulazione nel codice – DixonD

+0

Modificata la risposta per collegare un post di blog sull'utilizzo di PowerMock per questo tipo di test (fa leva sulla manipolazione di ClassLoader) – jayshao

7

Declinazione di responsabilità: non l'ho provato su una piattaforma non Windows, quindi potrebbe avere risultati diversi su una piattaforma con caratteristiche di blocco file diverse.

Se si blocca il file in anticipo, è possibile attivare un IOException quando qualcosa tenta di leggere da esso:

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

Questo funziona anche se si è nello stesso thread.

Ecco alcuni esempi di codice:

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

Non funziona per me - utilizzando Ubuntu .. ma l'idea è bello :) –

+0

funziona su Windows – panny

1

Si potrebbe forzare un'eccezione richiamando il metodo da vicino il vostro 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 
    } 

Mi auguro che aiuta.

0

Si consiglia di non utilizzare FileNotFoundException. Se vuoi lanciare un'eccezione specifica per il file non esistente, vorrei controllare csvFile.exists().

Ad esempio, è possibile creare una directory csvFile. Ho provato il codice e lo gettai:

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

A mio parere, un file in realtà essere una directory non è la stessa di FileNotFound, eppure si comporta lo stesso in java.

0

Definire nel test un FileInputStream overload che genera un'eccezione

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); 
} 
Problemi correlati