Domanda

Sto scrivendo un test per un pezzo di codice che contiene una cattura IOException che sto cercando di coprire. Il try / catch è simile al seguente:

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

Il modo più semplice sembra fare in modo che FileOutputStream lanci un FileNotFoundException, ma forse sto andando in questo modo nel modo sbagliato.

Qualcuno là fuori ha qualche consiglio?

È stato utile?

Soluzione

Dal tuo commento:

  

Sì, suppongo che la domanda dovrebbe   sono stato davvero " Come faccio a creare un   file che non esiste su entrambi Linux   e Windows? " Su Windows, posso usare   'nuovo file (" X: / ")', dove X: è un'unità   lettera che non esiste. Su Linux,   questo non funziona perché quello è un   nome file valido.

Guarda java.io.File.createTempFile. Usalo per creare il file e quindi eliminarlo.

Probabilmente passa qualcosa del tipo:

File tempFile;

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

Ciò dovrebbe darti un nome univoco in modo indipendente dalla piattaforma che puoi tranquillamente usare senza (molto) timore che esista.

Altri suggerimenti

È possibile impostare cacheFileName su un nome non valido o su uno che non esiste.

Ci sono due parti in ogni test: far sì che avvenga e misurare che hai ottenuto il risultato corretto.

Iniezione guasti

La risposta più semplice è quella che è già stata menzionata, ovvero impostare cacheFileName su un file che non esisterà mai. Questa è probabilmente la risposta più pratica in questa situazione.

Tuttavia, per causare una condizione arbitraria come un IOException , ciò che veramente vuoi è Iniezione guasti . Questo impone errori nel tuo codice senza forzarti a strumentare il tuo codice sorgente. Ecco alcuni metodi per farlo:

  • Oggetti finti È possibile utilizzare un metodo factory per creare un ObjectOutputStream o FileOutputStream sovrascritto. Nel codice di test l'implementazione genererebbe un IOException quando lo si desidera e nel codice di produzione non modifica il comportamento normale.
  • Iniezione delle dipendenze Per ottenere il Mock Object nel posto giusto, è possibile utilizzare un framework come Spring o Seam per " iniettare " l'oggetto appropriato nella classe che sta facendo il lavoro. Potete vedere che questi framework hanno persino una priorità per gli oggetti che verranno iniettati, in modo che durante il test unitario sia possibile sovrascrivere gli oggetti di produzione con oggetti test.
  • Programmazione orientata agli aspetti Invece di cambiare la struttura del tuo codice, puoi usare AOP per iniettare l'errore nel posto giusto. Ad esempio, usando AspectJ potresti definire un Pointcut da dove vuoi che venga generata l'eccezione e hai il Consigli getta l'eccezione desiderata.

Ci sono altre risposte all'iniezione di errori su Java; per esempio un prodotto chiamato AProbe ha aperto la strada a quello che potrebbe essere chiamato AOP in C molto tempo fa, e anche avere un prodotto Java.

Validation

Ottenere l'eccezione generata è un buon inizio, ma devi anche confermare che hai ottenuto il risultato giusto. Supponendo che l'esempio di codice che hai lì sia corretto, vuoi confermare che hai registrato quell'eccezione. Qualcuno sopra menzionato utilizza un oggetto Mock per il tuo logger, che è un'opzione praticabile. Puoi anche usare AOP qui per prendere la chiamata al logger.

Presumo che il logger sia log4j ; per risolvere un problema simile, ho implementato il mio appender log4j che cattura l'output di log4j: in particolare acquisisco solo ERROR e FATAL , che sono probabilmente i messaggi di log interessanti in tali un caso. L'appender viene indicato in log4j.xml e viene attivato durante l'esecuzione del test per acquisire l'output del registro errori. Questo è essenzialmente un oggetto finto, ma non ho dovuto ristrutturare tutto il mio codice che ha ottenuto un log4j Logger .

  

Sto scrivendo un test per un pezzo di codice   che contiene un IOException   che sto cercando di coprire.

Non sono del tutto sicuro di comprendere il tuo obiettivo, ma se vuoi verificare se viene generata l'eccezione, puoi dire al test che ti aspetti che generi l'eccezione:

@Test(expected=IOException.class)

Il test fallirà quindi se l'eccezione non viene generata e avrà esito positivo se viene generato (come se il file cacheFileName non esiste).

Un FileNotFoundException avrebbe ovviamente innescato la cattura. Il javadoc indica i casi in cui verrà lanciato.

Dovresti anche considerare che il costruttore ObjectOutputStream può lanciare una IOException, quindi potresti voler coprire questo caso nei tuoi test.

Due semplici modi sarebbero o impostare cacheFileName su un file inesistente o impostare il file specificato in accesso di sola lettura.

-John

Mentre il codice è attualmente scritto, potresti provare a simulare la chiamata di errore () sull'oggetto LOGGER e verificare se viene chiamato quando ti aspetti un'eccezione IO.

Il tuo desiderio di testare potrebbe aver scoperto un problema fondamentale con il codice mentre è scritto. Si è verificato un errore ma non esiste un valore booleano o flag (imposta il nome file su un modello speciale) che fornisca altre sezioni di codice per determinare se la scrittura nel file ha avuto esito positivo. Se questo è contenuto in una funzione, forse potresti restituire un valore booleano o impostare una variabile a livello di oggetto.

cacheFileName = "thisFileShouldNeverExistAndIfItDoesYouAreScrewingUpMyTests";

Sicuro che potresti fare dei passi e saltare attraverso i cerchi per assicurarti che il nome del file non esista mai, mai e poi mai, o potresti usare una stringa che non esisterà mai nel 99,99999% dei casi.

Spero che questo sia ciò che intendevi.

if(new File(cachedFile).exists()) {
    oos = new ObjectOutputStream(new FileOutputStream(cacheFileName));
    //do your code here
} else {
    throw new FileNotFoundException("File doesn't exist!");
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top