2015-09-28 18 views
5

Questo è sicuramente un problema comune. Ho un file di proprietà come my-settings.properties che viene letto da una classe di applicazione. Quando scrivo una classe di test, è necessario testare diversi scenari di cose che potrebbero essere presenti in my-settings.properties per garantire la massima copertura del codice (ad esempio file di proprietà vuoto, file di proprietà di base ecc.). Ma posso avere solo uno my-settings.properties nel mio src/test/resources.Come posso prendere in giro la presenza di un file di proprietà sul classpath?

Quale sarebbe davvero grande è se ci fosse solo alcune annotazioni

@MockFileOnClassPath(use = "my-settings-basic.properties", insteadOf = "my-settings.properties")

Poi ho potuto solo avere più file my-settings-XXX.properties nel mio /src/test/resources ed appena annotato quella corretta per ogni metodo di prova. Ma non riesco a trovare nulla di simile. Sto usando JUnit 4.12.

mi viene in mente un paio di soluzioni greggio:

  1. Prima di ogni prova, trovare il file sul file system, copiare utilizzando filesystem di I/O, quindi eliminarlo di nuovo dopo il test. Ma questo è maldestro e comporta molta ridondanza. Per non parlare del fatto che non sono nemmeno sicuro se la directory classpath sarà scrivibile.
  2. Utilizzare una struttura di simulazione per simulare getResource. Non ho idea di come avrei nemmeno farlo, soprattutto perché ci sono un milione di modi diversi per ottenere il file (, MyClass.class.getResourceAsStream(...), ClassLoader.getSystemClassLoader().getResourceAsStream(...) ecc)

Penso solo che questo deve essere un problema comune e forse c'è già una soluzione in JUnit, Mockito, PowerMock, EasyMock o qualcosa del genere?

MODIFICA: qualcuno ha specificato che questa domanda è un duplicato di Specifying a custom log4j.properties file for all of JUnit tests run from Eclipse ma non lo è. Questa domanda riguarda il voler avere un file di proprietà diverso tra le chiamate principali e quelle di test. Per me voglio avere un file di proprietà diverso tra una chiamata di test e un'altra chiamata di test.

+1

Questa è davvero una buona domanda. Stai recuperando un oggetto 'Proprietà' abbastanza spesso da essere in grado di cancellarlo?Anche se ci sono milioni di modi per ottenere le proprietà, il tuo codice accede al file delle proprietà in modo uniforme, il che eliminerebbe alcuni dei tuoi vettori di test che dovresti prendere in giro? O è una scatola nera e non lo sai? –

+1

Attualmente il mio codice recupera le proprietà in modo uniforme, ma non voglio che il test fallisca in futuro solo perché qualcuno ha cambiato il modo in cui è stato recuperato un file delle proprietà. Non sei sicuro di cosa intendi con "mozzalo". Vuoi dire che mock il costruttore e il metodo 'load' della classe' Properties' per non fare nulla, quindi prendi in giro il metodo 'getProperty' per restituire solo le proprietà da una mappa che ho creato nella mia classe di test? Questa è una buona idea ... anche se non sarebbe di aiuto verificare che stia passando il nome file corretto a 'getResourceAsStream' (ecc.) – Kidburla

+0

Sì, è quello che sto proponendo, e hai ragione, non è a prova di futuro. Sento che verificare il nome corretto del file dovrebbe essere un test diverso ... –

risposta

1

Trovo che ogni volta che si tratta di file, è meglio introdurre il concetto di Resource.

esempio:

public interface Resource { 
    String getName(); 
    InputStream getStream(); 
} 

Poi si può passare la risorsa in via iniezione di dipendenza:

public class MyService { 
    private final Properties properties; 

    public class MyService(Resource propFile) { 
     this.properties = new Properties(); 
     this.properties.load(propFile.getStream()); 
    } 

    ... 
} 

Poi, nel codice di produzione è possibile utilizzare un ClasspathResource o forse un FileResource o URLResource ecc, ma nei tuoi test potresti avere un StringResource ecc.

Nota, se usi la primavera hai già un impl enfatizzazione di questo concetto. Maggiori dettagli here

+0

Gli utenti della mia classe non dovrebbero aver bisogno di sapere dove si trova il file delle proprietà. Naturalmente, potrei creare un costruttore nullary che passa semplicemente 'DEFAULT_RESOURCE' al costruttore di argomento singolo, ma il mio utente sta chiamando un metodo diverso dalla mia classe di test. – Kidburla

+0

Questo è quello che farei, è comune aggiungere metodi per rendere più semplice il test ... Io renderei il costruttore protetto da un argomento piuttosto che pubblico poiché è solo per il test –

+0

Oh, intendi il pacchetto protetto? Questa potrebbe essere la migliore idea delle soluzioni disponibili. Mi sento ancora abbastanza sorpreso che non ci sia una soluzione pronta per questo problema! – Kidburla

2

È possibile modificare la classe Service per accettare il nome del file resource, quindi quindi utilizzare tale name per caricare il resource.

public class MyService { 

public MyService(String resourceFileName){ 
    //and load it into Properties getResourceAsStream(resourceFileName); 
} 
} 
+0

Questo è fondamentalmente ciò che @LanceJava ha suggerito, solo con una risorsa piuttosto che una stringa ... – Kidburla