Come ottenere il percorso della directory src / test / resources in JUnit?


275

So di poter caricare un file da src / test / resources con:

getClass().getResource("somefile").getFile()

Ma come posso ottenere il percorso completo della directory src / test / resources , cioè non voglio caricare un file, voglio solo conoscere il percorso della directory?


1
Per curiosità: perché vuoi saperlo?
fge,

3
@fge è necessario passarlo all'oggetto in prova, che lo utilizza per caricare un file
Rory

5
L'accesso diretto ai file nella directory delle risorse è una cattiva idea. Rifattorizza il codice in modo che funzioni a vapore o fai in modo che il tuo test crei prima una copia in una cartella temporanea.
Oliver Charlesworth,

4
@OliverCharlesworth Sono d'accordo sulle cartelle temporanee e lo uso org.junit.rules.TemporaryFoldersempre ... ma ... per copiare da test / risorse devi sapere, ehm, il suo percorso!
mike rodent,

1
@mikerodent - quello che penso intendesse era: leggere la risorsa tramite un inputstream, quindi scriverla in un file temporaneo.
Oliver Charlesworth,

Risposte:


204

Prova a lavorare con la ClassLoaderclasse:

ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("somefile").getFile());
System.out.println(file.getAbsolutePath());

A ClassLoaderè responsabile del caricamento in classe. Ogni classe ha un riferimento a ClassLoader. Questo codice restituisce un Filedalla directory delle risorse. Chiamandolo getAbsolutePath()restituisce il suo assoluto Path.

Javadoc per ClassLoader: http://docs.oracle.com/javase/7/docs/api/java/lang/ClassLoader.html


34
Questa non è necessariamente una buona idea. Se la risorsa è in un vaso, questo porterà a tempi tristi.
Oliver Charlesworth,

1
@OliverCharlesworth Quindi, cosa si può fare in caso di vaso?
Anmol Singh Jaggi,

@AnmolSinghJaggi - Vedi il mio commento sotto la domanda originale :)
Oliver Charlesworth,

maven build fallisce quando uso questa soluzione
firstpostcommenter

Sarà anche con il nome file
qwert_ukg

299

Non è necessario pasticciare con i caricatori di classi. In effetti è una cattiva abitudine entrare perché non lo sono le risorse del caricatore di classi oggetti java.io.File quando si trovano in un archivio jar.

Maven imposta automaticamente la directory di lavoro corrente prima di eseguire i test, quindi puoi semplicemente usare:

    File resourcesDirectory = new File("src/test/resources");

resourcesDirectory.getAbsolutePath() restituirà il valore corretto se questo è ciò di cui hai veramente bisogno.

Raccomando di creare una src/test/datadirectory se si desidera che i test accedano ai dati tramite il file system. Questo chiarisce cosa stai facendo.


4
nuovo file ("src / test / resources / fileXYZ"); non funzionerà. Né da Eclipse né da Maven se lo metti semplicemente in un test JUnit.
seba.wagner,

11
Funziona benissimo da Maven. In eclipse dovrai impostare la directory di lavoro corrente nel test runner, ma la riga di comando maven lo fa per te.
Steve C,

4
Io non la penso così. E perché dovresti farlo se puoi semplicemente fare un "nuovo file (getClass (). GetClassLoader (). GetResource (" fileNameXYZ.xml ")" senza la necessità di impostare nulla. Né in Eclipse né in Maven.
seba .wagner,

10
Piuttosto, perché non dovresti seguire gli standard della tua utility di compilazione? Soprattutto quando semplifica il tuo codice. Utilizzando IntelliJ o Maven, non è necessario impostare la directory di lavoro. Questa è ovviamente la soluzione più semplice, con Eclipse come un dolore come sempre.
James Watkins,

2
Per la versione IntelliJ 2014, dovevo ancora cambiare la directory di lavoro nelle configurazioni Run / Debug del metodo / classe di test, come menzionato da @Steve C.
a_secenthusiast

76

Vorrei semplicemente usare Pathda Java 7

Path resourceDirectory = Paths.get("src","test","resources");

Ordinato e pulito!


Questo stesso codice funzionerà esattamente su Windows? JavaDoc per Paths.get(...)suggerisce (comunque a me) che non lo farà.
Steve C

@SteveC puoi usare la File.separatorcostante per costruire la stringa da usare come percorso
JeanValjean

1
Lo so, ma è molto brutto. Al contrario, new File("src/test/resources")fa la cosa giusta su tutte le piattaforme.
Steve C

2
Perché non usare solo Path resourceDirectory = Paths.get("src","test","resources");?
Navneeth,

1
Hmm, Paths.get("src", "test", "resources")e Paths.get("src/test/resources")funziona bene su Windows 10 per me. Che cosa sto facendo di sbagliato? =)
naXa

24

Se si tratta di un progetto di primavera, possiamo usare il codice seguente per ottenere i file dalla cartella src / test / resource .

File file = ResourceUtils.getFile(this.getClass().getResource("/some_file.txt"));

14

Ho un progetto Maven3 con JUnit 4.12 e Java8. Per ottenere il percorso di un file chiamato myxml.xmlunder src/test/resources, lo faccio all'interno del test case:

@Test
public void testApp()
{
    File inputXmlFile = new File(this.getClass().getResource("/myxml.xml").getFile());
    System.out.println(inputXmlFile.getAbsolutePath());
    ...
}

Testato su Ubuntu 14.04 con IntelliJ IDE. Riferimento qui .


11

Tutto il contenuto in src/test/resourcesviene copiato nella target/test-classescartella. Quindi per ottenere il file dalle risorse di test durante la compilazione di Maven devi caricarlo dalla test-classescartella, in questo modo:

Paths.get(
    getClass().getProtectionDomain().getCodeSource().getLocation().toURI()
).resolve(
    Paths.get("somefile")
).toFile()

Abbattersi:

  1. getClass().getProtectionDomain().getCodeSource().getLocation().toURI()- ti dà URI a target/test-classes.
  2. resolve(Paths.get("somefile"))- risolve someFilein target/test-classescartella.

Anwser originale è tratto da questo


8

Esistono differenze e vincoli nelle opzioni offerte da @Steve C e @ ashosborne1. Devono essere specificati, credo.

Quando possiamo usare File resourcesDirectory = new File("src/test/resources");:?

  • 1 Quando i test verranno eseguiti solo tramite Maven ma non tramite IDE.
  • 2.1 Quando i test verranno eseguiti tramite Maven o
  • 2.2 tramite IDE e un solo progetto viene importato in IDE. (Uso il termine "importato", perché è usato in IntelliJ IDEA. Penso che anche gli utenti di eclipse importino il loro progetto maven). Questo funzionerà, perché la directory di lavoro quando esegui i test tramite IDE è uguale al tuo progetto.
  • 3.1 Quando i test verranno eseguiti tramite Maven o
  • 3.2 tramite IDE e più di un progetto viene importato in IDE (quando non sei uno studente, di solito importa diversi progetti) E prima di eseguire i test tramite IDE, devi configurare manualmente la directory di lavoro per i tuoi test. Tale directory di lavoro dovrebbe fare riferimento al progetto importato che contiene i test. Per impostazione predefinita, la directory di lavoro di tutti i progetti importati in IDE è solo una. Probabilmente è solo una limitazione IntelliJ IDEA, ma penso che tutti gli IDE funzionino in questo modo. E questa configurazione che deve essere eseguita manualmente, non è affatto buona. Lavorando con diversi test esistenti in diversi progetti maven, ma importati in un unico grande progetto "IDE", ci costringono a ricordare questo e non permettiamo di rilassarci e trarre piacere dal tuo lavoro.

La soluzione offerta da @ ashosborne1 (personalmente preferisco questa) richiede 2 requisiti aggiuntivi che devono essere eseguiti prima di eseguire i test. Ecco un elenco di passaggi per utilizzare questa soluzione:

  • Creare una cartella di prova ("teva") e un file ("readme") all'interno di "src / test / resources /":

    src / test / risorse / teva / readme

    Il file deve essere creato nella cartella di prova, altrimenti non funzionerà. Maven ignora le cartelle vuote.

  • Almeno una volta costruisci il progetto tramite mvn clean install. Eseguirà anche test. Potrebbe essere sufficiente eseguire solo la classe / il metodo di test tramite Maven senza creare un intero progetto. Di conseguenza le tue risorse di test verranno copiate in classi di test, ecco un percorso:target/test-classes/teva/readme

  • Successivamente, puoi accedere alla cartella utilizzando il codice, già offerto da @ ashosborne1 (mi dispiace, non ho potuto modificare correttamente questo codice all'interno di questo elenco di elementi):

public static final String TEVA_FOLDER = "teva"; ... 
URL tevaUrl = YourTest.class.getClassLoader().getResource(TEVA_FOLDER); 
String tevaTestFolder = new File(tevaUrl.toURI()).getAbsolutePath();

Ora puoi eseguire il test tramite IDE tutte le volte che vuoi. Fino a quando non esegui mvn clean. Rilascerà la cartella di destinazione.

La creazione di file all'interno di una cartella di test e l'esecuzione di maven la prima volta, prima di eseguire i test tramite IDE, sono necessari passaggi. Senza questi passaggi, se solo nel tuo IDE crei risorse di test, quindi scrivi test ed eseguilo solo tramite IDE, otterrai un errore. L'esecuzione dei test tramite mvn copia le risorse di test in target / test-classes / teva / readme e diventano accessibili per un classloader.

Potresti chiedere, perché devo importare più di un progetto maven in IDE e perché così tante cose complicate? Per me, una delle principali motivazioni: mantenere i file relativi a IDA lontani dal codice. Per prima cosa creo un nuovo progetto nel mio IDE. È un progetto falso, che è solo un detentore di file relativi a IDE. Quindi, importare progetti di maven già esistenti. Costringo questi progetti importati a conservare i file IDEA solo nel mio progetto falso originale. Di conseguenza non vedo i file relativi a IDE nel codice. SVN non dovrebbe vederli (non offrire di configurare svn / git per ignorare tali file, per favore). Inoltre è solo molto conveniente.


Ciao Alexandr, sono nei guai con il file di risorse in target / classi e src / main / resource e sembri l'unico a parlarne. Per prima cosa ho i file su src / main / resource, dopo aver compilato il progetto, copia questi file in target / classi. E da questo, getClass (). GetClassLoader (). GetResource (fileName) funziona solo sulla cartella di destinazione mentre voglio che io lavori su src / main. Puoi darmi un link da qualche parte spiegare sul meccanismo del file getResource? come configurare la cartella delle risorse? Tks: D
Huy Hóm Hỉnh,

2
@Huy Hóm Hỉnh, consiglierei di non farlo. Temo che tu vada nella direzione sbagliata. Ci sono alcuni posti in cui si trovano i file di risorse, i posti sono noti per tutti gli altri. Più facile mantenere tali progetti. Anche per te sarà più facile, devi solo capire la struttura dei progetti di Maven. Ma di sicuro, puoi configurare l'ubicazione predefinita delle risorse con [ maven.apache.org/plugins/maven-resources-plugin/examples/…
Alexandr

@ HuyHómHỉnh, dai un'occhiata anche alla soluzione qui: stackoverflow.com/questions/23289098/… Ma per configurare src / main come risorsa ... Cerca di evitarlo, sembra che tu stia facendo qualcosa di sbagliato.
Alexandr

hm. Potresti elaborare cosa c'è che non va .gitignore? Inoltre sembra che IDEA esegua Maven automaticamente durante l'esecuzione dei test (e imposta la directory di lavoro corretta per impostazione predefinita $MODULE_DIR$). Quindi non è necessario eseguire mvn testmanualmente prima di tutto, tutto funziona bene sia con Maven che con IDEA "src/test/resources/somefile.txt".
Alex P.

5

La soluzione più semplice e pulita che utilizzo, supponiamo che il nome della classe di test sia TestQuery1e che ci sia una resourcesdirectory nella testcartella come segue:

├── java
   └── TestQuery1.java
└── resources
    └── TestQuery1
        ├── query.json
        └── query.rq

Per ottenere l'URI di TestQuery1do:

URL currentTestResourceFolder = getClass().getResource("/"+getClass().getSimpleName());

Per ottenere l'URI di uno dei file TestQuery1, eseguire:

File exampleDir = new File(currentTestResourceFolder.toURI());
URI queryJSONFileURI = exampleDir.toURI().resolve("query.json");

1
Nessun problema, infatti grazie per il tuo aiuto !! La cosa buona è che eliminando la tua risposta, sono in grado di eliminare la domanda. Sì, abbastanza frustrato anche qui, ma comunque grazie !! Buona sera :)
Noor,

1

Non è possibile utilizzare un file da una cartella di risorse per i test in un caso comune. Il motivo è che i file di risorse nella cartella delle risorse sono memorizzati in un barattolo. Quindi non hanno un vero percorso nel file system.

La soluzione più semplice può essere:

  1. Copia un file dalle risorse nella cartella temporanea e ottieni un percorso per quel file temporaneo.
  2. Esegui i test utilizzando un percorso temporaneo.
  3. Elimina il file temporaneo.

TemporaryFolderda JUnitpuò essere utilizzato per creare i file temporanei ed eliminarlo dopo la prova è completata. Le classi dalla guavalibreria vengono utilizzate per copiare una cartella di risorse del modulo file.

Si noti che se si utilizza una sottocartella nella cartella delle risorse, come gooduna, non è necessario aggiungere lead /al percorso delle risorse.

public class SomeTest {

    @Rule
    public TemporaryFolder tmpFolder = new TemporaryFolder();


    @Test
    public void doSomethinge() throws IOException {
        File file = createTmpFileFromResource(tmpFolder, "file.txt");
        File goodFile = createTmpFileFromResource(tmpFolder, "good/file.txt");

        // do testing here
    }

    private static File createTmpFileFromResource(TemporaryFolder folder,
                                                  String classLoaderResource) throws IOException {
        URL resource = Resources.getResource(classLoaderResource);

        File tmpFile = folder.newFile();
        Resources.asByteSource(resource).copyTo(Files.asByteSink(tmpFile));
        return tmpFile;
    }

}

0

Utilizzare quanto segue per iniettare Hibernate con Spring nei test unitari:

@Bean
public LocalSessionFactoryBean getLocalSessionFactoryBean() {
    LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
    localSessionFactoryBean.setConfigLocation(new ClassPathResource("hibernate.cfg.xml"));
    localSessionFactoryBean.setPackagesToScan("com.example.yourpackage.model");
    return localSessionFactoryBean;
}

Se non hai il hibernate.cfg.xmlpresente nella tua src/test/resourcescartella, tornerà automaticamente a quello nella tua src/main/resourcescartella.


0

Utilizzare .getAbsolutePath () sull'oggetto File.

getClass().getResource("somefile").getFile().getAbsolutePath()

getFile return Istanza di stringa non FIle
Almas Abdrazak il

@AlmasAbdrazak GreatDantone non dice che getFile()restituisce un'istanza di file. Dice che getAbsolutePath()viene utilizzato su un'istanza di oggetto File.
menteith

@menteith Secondo il suo codice, chiama getFile () e quindi getAbsolutePath () su getFile () ma getFile () restituisce String e non è possibile chiamare getAbsolutePath () su oggetto String
Almas Abdrazak

0

Con Spring puoi facilmente leggerlo dalla cartella delle risorse (principale / risorse o test / risorse):

Ad esempio creare un file: test/resources/subfolder/sample.json

@Test
public void testReadFile() {
    String json = this.readFile("classpath:subfolder/sample.json");
    System.out.println(json);
}

public String readFile(String path) {
    try {
        File file = ResourceUtils.getFile(path);
        return new String(Files.readAllBytes(file.toPath()));
    } catch (IOException e) {
        e.printStackTrace();
    }

    return null;
}

0
List<String> lines = Files.readAllLines(Paths.get("src/test/resources/foo.txt"));
lines.forEach(System.out::println);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.