Wie erhalte ich den Pfad des Verzeichnisses src / test / resources in JUnit?

275

Ich weiß, dass ich eine Datei aus src / test / resources laden kann mit:

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

Aber wie kann ich den vollständigen Pfad zum Verzeichnis src / test / resources abrufen , dh ich möchte keine Datei laden, sondern nur den Pfad des Verzeichnisses kennen?

Rory
quelle
1
Aus Neugier: Warum willst du das wissen?
fge
3
@fge muss es an das zu testende Objekt übergeben, das es zum Laden einer Datei verwendet
Rory
5
Direkter Dateizugriff auf Ihr Ressourcenverzeichnis ist eine schlechte Idee. Überarbeiten Sie Ihren Code, um mit Dampf zu arbeiten, oder lassen Sie Ihren Test zuerst eine Kopie in einem temporären Ordner erstellen.
Oliver Charlesworth
4
@OliverCharlesworth Ich stimme temporären Ordnern zu und benutze sie org.junit.rules.TemporaryFolderständig ... aber ... um von Tests / Ressourcen zu kopieren, die Sie kennen müssen, ähm, ihren Pfad!
Mike Nagetier
1
@mikerodent - was meiner Meinung nach bedeutete: Lesen Sie die Ressource über einen Eingabestream und schreiben Sie sie dann in eine temporäre Datei.
Oliver Charlesworth

Antworten:

204

Versuchen Sie, mit der ClassLoaderKlasse zu arbeiten:

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

A ClassLoaderist für das Laden in Klassen verantwortlich. Jede Klasse hat einen Verweis auf a ClassLoader. Dieser Code gibt a Fileaus dem Ressourcenverzeichnis zurück. Wenn Sie getAbsolutePath()es aufrufen, wird das Absolute zurückgegeben Path.

Javadoc für ClassLoader: http://docs.oracle.com/javase/7/docs/api/java/lang/ClassLoader.html

ashosborne1
quelle
34
Dies ist nicht unbedingt eine gute Idee. Wenn sich die Ressource in einem Glas befindet, führt dies zu traurigen Zeiten.
Oliver Charlesworth
1
@OliverCharlesworth Also, was kann man im Falle eines Glases tun?
Anmol Singh Jaggi
@AnmolSinghJaggi - Siehe meinen Kommentar unter der ursprünglichen Frage :)
Oliver Charlesworth
Maven Build schlägt fehl, wenn ich diese Lösung verwende
firstpostcommenter
Es wird auch mit Dateinamen sein
qwert_ukg
299

Sie müssen sich nicht mit Klassenladern anlegen. Tatsächlich ist es eine schlechte Angewohnheit, sich darauf einzulassen, da Klassenladeprogrammressourcen keine java.io.File-Objekte sind, wenn sie sich in einem JAR-Archiv befinden.

Maven legt automatisch das aktuelle Arbeitsverzeichnis fest, bevor Tests ausgeführt werden. Sie können also einfach Folgendes verwenden:

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

resourcesDirectory.getAbsolutePath() gibt den korrekten Wert zurück, wenn Sie dies wirklich benötigen.

Ich empfehle, ein src/test/dataVerzeichnis zu erstellen, wenn Ihre Tests über das Dateisystem auf Daten zugreifen sollen. Dies macht deutlich, was Sie tun.

Steve C.
quelle
4
neue Datei ("src / test / resources / fileXYZ"); wird nicht funktionieren. Weder von Eclipse noch von Maven, wenn Sie das einfach einem JUnit-Test unterziehen.
seba.wagner
11
Es funktioniert gut von Maven. In Eclipse müssen Sie das aktuelle Arbeitsverzeichnis im Test Runner festlegen, aber der Befehlszeilen-Maven erledigt dies für Sie.
Steve C
4
Das glaube ich nicht. Und warum sollten Sie das tun, wenn Sie einfach eine "neue Datei (getClass (). GetClassLoader (). GetResource (" fileNameXYZ.xml ")" "erstellen können, ohne etwas einrichten zu müssen. Weder in Eclipse noch in Maven.
seba .wagner
10
Warum sollten Sie nicht den Standards Ihres Build-Dienstprogramms folgen? Besonders wenn es Ihren Code vereinfacht. Mit IntelliJ oder Maven muss kein Arbeitsverzeichnis festgelegt werden. Dies ist offensichtlich die einfachste Lösung, da Eclipse wie immer ein Schmerz ist.
James Watkins
2
Für die IntelliJ 2014-Version musste ich das Arbeitsverzeichnis in den Run / Debug-Konfigurationen der Testmethode / -klasse noch ändern, wie in @Steve C erwähnt.
a_secenthusiast
76

Ich würde einfach Pathvon Java 7 verwenden

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

Ordentlich und sauber!

Jean Valjean
quelle
Funktioniert genau dieser Code unter Windows? Das JavaDoc für Paths.get(...)schlägt (für mich jedenfalls) vor, dass es nicht wird.
Steve C
@SteveC Sie können File.separatorKonstante verwenden, um die Zeichenfolge zu erstellen, die als Pfad verwendet werden soll
JeanValjean
1
Ich weiß das, aber es ist sehr hässlich. Im Gegensatz dazu new File("src/test/resources")macht das Richtige auf allen Plattformen.
Steve C
2
Warum nicht einfach benutzen Path resourceDirectory = Paths.get("src","test","resources");?
Navneeth
1
Hmm, Paths.get("src", "test", "resources")und Paths.get("src/test/resources")funktioniert gut unter Windows 10 für mich. Was mache ich falsch? =)
naXa
24

Wenn es sich um ein Frühjahrsprojekt handelt, können wir den folgenden Code verwenden, um Dateien aus dem Ordner src / test / resource abzurufen.

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

Ich habe ein Maven3-Projekt mit JUnit 4.12 und Java8. Um den Pfad einer Datei zu erhalten, die myxml.xmlunter aufgerufen wird src/test/resources, mache ich dies aus dem Testfall heraus:

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

Getestet unter Ubuntu 14.04 mit IntelliJ IDE. Referenz hier .

Antonius
quelle
11

Der gesamte Inhalt src/test/resourceswird in einen target/test-classesOrdner kopiert . Um also während des Maven-Builds eine Datei aus den Testressourcen abzurufen, müssen Sie sie test-classeswie folgt aus dem Ordner laden :

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

Nervenzusammenbruch:

  1. getClass().getProtectionDomain().getCodeSource().getLocation().toURI()- Gib dir URI zu target/test-classes.
  2. resolve(Paths.get("somefile"))- wird someFilein target/test-classesOrdner aufgelöst.

Original anwser ist entnommen aus dieser

Kirsche
quelle
8

Es gibt Unterschiede und Einschränkungen bei den von @Steve C und @ ashosborne1 angebotenen Optionen. Sie müssen spezifiziert werden, glaube ich.

Wann können wir verwenden : File resourcesDirectory = new File("src/test/resources");?

  • 1 Wenn Tests nur über Maven, nicht aber über IDE ausgeführt werden sollen.
  • 2.1 Wenn Tests über maven oder ausgeführt werden sollen
  • 2.2 über IDE und nur ein Projekt wird in IDE importiert. (Ich verwende den Begriff "importiert", da er in IntelliJ IDEA verwendet wird. Ich denke, Benutzer von Eclipse importieren auch ihr Maven-Projekt.) Dies funktioniert, da das Arbeitsverzeichnis beim Ausführen von Tests über IDE mit Ihrem Projekt identisch ist.
  • 3.1 Wenn Tests über maven oder ausgeführt werden sollen
  • 3.2 über IDE, und mehr als ein Vorhaben in IDE importiert (wenn Sie kein Student sind, in der Regel Sie mehrere Projekte importieren), und bevor Sie Tests über IDE ausführen, können Sie manuell konfigurieren für Ihre Tests Arbeitsverzeichnis. Dieses Arbeitsverzeichnis sollte sich auf Ihr importiertes Projekt beziehen, das die Tests enthält. Standardmäßig ist das Arbeitsverzeichnis aller in IDE importierten Projekte nur eines. Wahrscheinlich ist es nur eine Einschränkung IntelliJ IDEA, aber ich denke, alle IDEs funktionieren so. Und diese Konfiguration, die manuell vorgenommen werden muss, ist überhaupt nicht gut. Wenn wir mit mehreren Tests arbeiten, die in verschiedenen Maven-Projekten vorhanden sind, aber in ein großes „IDE“ -Projekt importiert wurden, müssen wir uns daran erinnern und dürfen uns nicht entspannen und Freude an Ihrer Arbeit haben.

Die von @ ashosborne1 angebotene Lösung (ich persönlich bevorzuge diese) erfordert zwei zusätzliche Anforderungen, die erfüllt sein müssen, bevor Sie Tests ausführen. Hier ist eine Liste der Schritte zur Verwendung dieser Lösung:

  • Erstellen Sie einen Testordner ("teva") und eine Datei ("readme") in "src / test / resources /":

    src / test / resources / teva / readme

    Die Datei muss im Testordner erstellt werden, sonst funktioniert sie nicht. Maven ignoriert leere Ordner.

  • Mindestens einmal Projekt über erstellen mvn clean install. Es werden auch Tests ausgeführt. Es kann ausreichen, nur Ihre Testklasse / -methode über maven auszuführen, ohne ein ganzes Projekt zu erstellen. Als Ergebnis werden Ihre Testressourcen in Testklassen kopiert. Hier ist ein Pfad:target/test-classes/teva/readme
  • Danach können Sie mit Code, der bereits von @ ashosborne1 angeboten wird, auf den Ordner zugreifen (es tut mir leid, dass ich diesen Code in dieser Liste der Elemente nicht korrekt bearbeiten konnte):
public static final String TEVA_FOLDER = "teva"; ... 
URL tevaUrl = YourTest.class.getClassLoader().getResource(TEVA_FOLDER); 
String tevaTestFolder = new File(tevaUrl.toURI()).getAbsolutePath();

Jetzt können Sie Ihren Test so oft über IDE ausführen, wie Sie möchten. Bis Sie mvn sauber laufen. Der Zielordner wird gelöscht.

Das Erstellen einer Datei in einem Testordner und das erstmalige Ausführen von maven, bevor Sie Tests über IDE ausführen, sind erforderliche Schritte. Wenn Sie ohne diese Schritte nur in Ihrer IDE Testressourcen erstellen, dann Test schreiben und nur über IDE ausführen, wird eine Fehlermeldung angezeigt. Durch Ausführen von Tests über mvn werden Testressourcen in target / test-classes / teva / readme kopiert und für einen Klassenladeprogramm zugänglich.

Sie fragen sich vielleicht, warum ich mehr als ein Maven-Projekt in IDE importieren muss und warum so viele komplizierte Dinge? Für mich eine der Hauptmotivationen: IDA-bezogene Dateien von Code fernzuhalten. Ich erstelle zuerst ein neues Projekt in meiner IDE. Es ist ein gefälschtes Projekt, das nur Inhaber von IDE-bezogenen Dateien ist. Dann importiere ich bereits vorhandene Maven-Projekte. Ich zwinge diese importierten Projekte, IDEA-Dateien nur in meinem ursprünglichen gefälschten Projekt zu behalten. Infolgedessen werden im Code keine IDE-bezogenen Dateien angezeigt. SVN sollte sie nicht sehen (bitte nicht anbieten, svn / git so zu konfigurieren, dass solche Dateien ignoriert werden). Auch ist es einfach sehr praktisch.

Alexandr
quelle
Hallo Alexandr, ich habe Probleme mit der Ressourcendatei in target / classes und src / main / resource und du scheinst der einzige zu sein, der darüber spricht. Zuerst habe ich Dateien auf src / main / resource, nach dem Erstellen des Projekts kopiert es diese Datei in target / classes. Und von diesem Punkt aus funktioniert getClass (). GetClassLoader (). GetResource (Dateiname) nur für den Zielordner, während ich für src / main arbeiten möchte. Können Sie mir irgendwo einen Link geben, der den Mechanismus der getResource-Datei erklärt? Wie konfiguriere ich den Ressourcenordner? Tks: D
Huy Hóm Hỉnh
2
@ Huy Hóm Hỉnh, ich würde empfehlen, es nicht zu tun. Ich fürchte, Sie gehen in die falsche Richtung. Es gibt bestimmte Orte, an denen sich Ressourcendateien befinden, die Orte sind für alle anderen bekannt. Einfachere Pflege solcher Projekte. Selbst für Sie wird es einfacher sein, Sie müssen nur die Struktur von Maven-Projekten verstehen. Aber sicher können Sie den Standardspeicherort für Ressourcen mit [ maven.apache.org/plugins/maven-resources-plugin/examples/…
Alexandr
@ HuyHómHỉnh, Schauen Sie sich auch die Lösung hier an: stackoverflow.com/questions/23289098/… Aber um Sie src / main als Ressource zu konfigurieren ... Versuchen Sie es zu vermeiden, es scheint, dass Sie etwas falsch machen.
Alexandr
Hm. Könnten Sie näher erläutern, was los ist .gitignore? Es sieht auch so aus, als würde IDEA Maven beim Ausführen von Tests automatisch ausführen (und standardmäßig das richtige Arbeitsverzeichnis festlegen $MODULE_DIR$). Es ist also nicht erforderlich, mvn testvorher manuell auszuführen , alles funktioniert sowohl mit Maven als auch mit IDEA mit nur einwandfrei "src/test/resources/somefile.txt".
Alex P.
5

Angenommen, der Name der Testklasse lautet TestQuery1und es befindet sich ein resourcesVerzeichnis in Ihrem testOrdner wie folgt:

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

So erhalten Sie die URI von TestQuery1do:

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

Gehen Sie folgendermaßen vor, um den URI einer der Dateien TestQuery1abzurufen:

File exampleDir = new File(currentTestResourceFolder.toURI());
URI queryJSONFileURI = exampleDir.toURI().resolve("query.json");
Noor
quelle
1
Keine Sorge, in der Tat danke für Ihre Hilfe! Das Gute ist, dass ich beim Löschen Ihrer Antwort die Frage löschen kann. Ja, auch hier draußen ziemlich frustriert, aber trotzdem danke !! Guten Abend :)
Noor
1

In einem häufigen Fall können Sie keine Datei aus einem Ressourcenordner für Tests verwenden. Der Grund dafür ist, dass Ressourcendateien im Ressourcenordner in einem JAR gespeichert werden. Sie haben also keinen richtigen Pfad im Dateisystem.

Die einfachste Lösung kann sein:

  1. Kopieren Sie eine Datei von Ressourcen in den temporären Ordner und erhalten Sie einen Pfad zu dieser temporären Datei.
  2. Führen Sie Tests mit einem temporären Pfad durch.
  3. Löschen Sie die temporäre Datei.

TemporaryFolderMit from JUnitkönnen temporäre Dateien erstellt und nach Abschluss des Tests gelöscht werden. Klassen vonguava Bibliothek werden zum Kopieren eines Ressourcenordners für Dateiformate verwendet.

Beachten Sie bitte, dass wir, wenn wir einen Unterordner im Ressourcenordner verwenden, wie z. B. goodeinen, keinen führenden /zum Ressourcenpfad hinzufügen müssen .

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

}
v.ladynev
quelle
0

Verwenden Sie Folgendes, um Hibernate mit Spring in Ihren Unit-Tests zu injizieren:

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

Wenn Sie das hibernate.cfg.xmlGeschenk nicht in Ihrem src/test/resourcesOrdner haben, wird es automatisch auf das in Ihrem src/main/resourcesOrdner zurückgesetzt.

Whitebrow
quelle
0

Verwenden Sie .getAbsolutePath () für Ihr Dateiobjekt.

getClass().getResource("somefile").getFile().getAbsolutePath()
GreatDantone
quelle
getFile return String Instanz nicht FIle
Almas Abdrazak
@AlmasAbdrazak GreatDantone sagt nicht, dass getFile()eine Dateiinstanz zurückgegeben wird . Er sagt, dass dies getAbsolutePath()für eine Instanz des Dateiobjekts verwendet wird.
Menteith
@menteith Gemäß seinem Code ruft er getFile () und dann getAbsolutePath () auf getFile () auf, aber getFile () gibt String zurück und Sie können getAbsolutePath () nicht auf String-Objekt aufrufen
Almas Abdrazak
0

Mit Spring können Sie es einfach aus dem Ressourcenordner lesen (entweder main / resources oder test / resources):

Erstellen Sie beispielsweise eine Datei: 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;
}
MevlütÖzdemir
quelle
0
List<String> lines = Files.readAllLines(Paths.get("src/test/resources/foo.txt"));
lines.forEach(System.out::println);
zhuguowei
quelle