JUnitのsrc / test / resourcesディレクトリのパスを取得する方法


275

私はsrc / test / resourcesからファイルをロードできることを知っています:

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

しかし、どうすればsrc / test / resources ディレクトリへのフルパスを取得できますか。つまり、ファイルをロードしたくないので、ディレクトリのパスを知りたいだけなのですか。


1
好奇心から:なぜ知りたいのですか?
2015

3
@fgeはそれをテスト対象オブジェクトに渡す必要があります。テスト対象オブジェクトを使用して、ファイルをロードします
Rory

5
リソースディレクトリへの直接フ​​ァイルアクセスはお勧めできません。Steamで動作するようにコードをリファクタリングするか、テストでまずTemporaryFolderにコピーを作成します。
オリバーチャールズワース2015

4
@OliverCharlesworth一時フォルダーについて同意し、org.junit.rules.TemporaryFolder常に使用します...しかし...テスト/リソースからコピーするには、知っている必要があります。
マイクげっ歯類

1
@mikerodent-私が考えたのは、入力ストリームを介してリソースを読み取り、一時ファイルに書き込むことでした。
オリバーチャールズワース

回答:


204

ClassLoaderクラスで作業してみてください:

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

A ClassLoaderはクラスのロードを担当します。すべてのクラスにはへの参照がありClassLoaderます。このコードはFile、リソースディレクトリからを返します。それを呼び出すgetAbsolutePath()と、その絶対値が返されますPath

のJavadoc ClassLoaderhttp : //docs.oracle.com/javase/7/docs/api/java/lang/ClassLoader.html


34
これは必ずしも良い考えではありません。リソースがjarファイルにある場合、これは悲しい時代につながります。
オリバーチャールズワース2015

1
@OliverCharlesworthでは、jarの場合はどうすればよいでしょうか。
Anmol Singh Jaggi 2017年

@AnmolSinghJaggi-元の質問の下にある私のコメントを参照してください:)
Oliver Charlesworth

このソリューションを使用するとmavenビルドが失敗する
firstpostcommenter

ファイル名も含まれます
qwert_ukg 2018年

299

クラスローダーをいじる必要はありません。実際、クラスローダーリソースがjarアーカイブにある場合、クラスローダーリソースはjava.io.Fileオブジェクトではないため、この習慣を身につけることは悪い習慣です。

Mavenはテストを実行する前に現在の作業ディレクトリを自動的に設定するため、次のコマンドを使用できます。

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

resourcesDirectory.getAbsolutePath() それが本当に必要な場合は、正しい値を返します。

src/test/dataテストでファイルシステムを介してデータにアクセスする場合は、ディレクトリを作成することをお勧めします。これにより、何をしているかが明確になります。


4
新しいファイル( "src / test / resources / fileXYZ"); 動作しないでしょう。単純にJUnitテストに入れれば、EclipseからもMavenからもなりません。
seba.wagner

11
Mavenからは問題なく動作します。日食では、テストランナーの現在の作業ディレクトリを設定する必要がありますが、コマンドラインmavenがこれを行います。
Steve C

4
そうは思いません。そして、「new File(getClass()。getClassLoader()。getResource( "fileNameXYZ.xml")」を何もセットアップする必要なく単純に実行できるのであれば、なぜそれを行うのでしょうか?EclipseでもMavenでも
seba .wagner

10
むしろ、ビルドユーティリティの標準に従っていないのはなぜですか。特にそれがあなたのコードを単純化するとき。IntelliJまたはMavenを使用すると、作業ディレクトリを設定する必要はありません。これは明らかに最も単純な解決策であり、Eclipseはいつものように面倒です。
James Watkins、

2
IntelliJ 2014バージョンの場合、@ Steve Cが言及したように、テストメソッド/クラスの実行/デバッグ構成の作業ディレクトリを変更する必要がありました。
a_secenthusiast 2016

76

私は単にPathJava 7から使用します

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

清楚な!


これとまったく同じコードはWindowsでも機能しますか?のJavaDocは、Paths.get(...)(とにかく私には)そうではないと示唆しています。
スティーブC

@SteveC File.separator定数を使用して、パスとして使用する文字列を作成できます
JeanValjean

1
私はそれを知っていますが、それは非常に醜いです。対照的に、new File("src/test/resources")すべてのプラットフォームで正しいことを行います。
スティーブC

2
なぜ使用しないのPath resourceDirectory = Paths.get("src","test","resources");ですか?
Navneeth、

1
うーん、Paths.get("src", "test", "resources")Paths.get("src/test/resources")私のためのWindows 10での作業罰金。何が悪いのですか?=)
naXa

24

Springプロジェクトの場合、以下のコードを使用してsrc / test / resourceフォルダーからファイルを取得できます。

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

14

JUnit 4.12とJava8を使用するMaven3プロジェクトがあります。myxml.xmlunder というファイルのパスを取得するためにsrc/test/resources、テストケース内からこれを実行します。

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

IntelliJ IDEを備えたUbuntu 14.04でテスト済み。参照はこちら


11

のすべてのコンテンツがフォルダにsrc/test/resourcesコピーされtarget/test-classesます。したがって、mavenビルド中にテストリソースからファイルを取得するにはtest-classes、次のようにフォルダーからファイルをロードする必要があります。

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

壊す:

  1. getClass().getProtectionDomain().getCodeSource().getLocation().toURI()-にURIを指定しtarget/test-classesます。
  2. resolve(Paths.get("somefile"))- フォルダーに解決さsomeFiletarget/test-classesます。

元のアンサーはこちらから


8

@Steve Cと@ ashosborne1が提供するオプションには違いと制約があります。特定する必要があると思います。

いつ使用できますFile resourcesDirectory = new File("src/test/resources");か?

  • 1テストがmaven経由でのみ実行され、IDE経由では実行されない場合。
  • 2.1テストがmavenまたは
  • 2.2 IDE経由で、1つのプロジェクトのみがIDEにインポートされます。(IntelliJ IDEAで使用されているため、「インポート」という用語を使用しています。EclipseのユーザーもMavenプロジェクトをインポートすると思います)。これは機能します。IDE経由でテストを実行すると、作業ディレクトリがプロジェクトと同じになります。
  • 3.1テストがmavenまたは
  • (あなたは、あなたは通常、いくつかのプロジェクトをインポートする学生でない場合)、IDE、および複数のプロジェクトを経由して3.2 IDEにインポートされている、あなたはIDEを経由してテストを実行する前に、手動で設定し、あなたのテストのための作業ディレクトリ。その作業ディレクトリは、テストを含むインポートされたプロジェクトを参照する必要があります。デフォルトでは、IDEにインポートされたすべてのプロジェクトの作業ディレクトリは1つだけです。おそらくそれIntelliJ IDEAだけの制限ですが、すべてのIDEはこのように動作すると思います。そして、手動で行わなければならないこの構成は、まったく良くありません。異なるmavenプロジェクトに存在するが、1つの大きな「IDE」プロジェクトにインポートされたいくつかのテストで作業する場合は、これを覚えさせ、リラックスして作業を楽にすることはできません。

@ ashosborne1が提供するソリューション(個人的には私が好む)は、テストを実行する前に実行する必要がある2つの追加要件を必要とします。このソリューションを使用する手順のリストは次のとおりです。

  • 「src / test / resources /」内にテストフォルダー(「teva」)とファイル(「readme」)を作成します。

    src / test / resources / teva / readme

    ファイルはテストフォルダーに作成する必要があります。作成しないと機能しません。Mavenは空のフォルダーを無視します。

  • 少なくとも1回、を介してプロジェクトをビルドしmvn clean installます。テストも実行します。プロジェクト全体をビルドせずに、Mavenを介してテストクラス/メソッドのみを実行するだけで十分な場合があります。結果として、テストリソースがテストクラスにコピーされます。パスは次のとおりです。target/test-classes/teva/readme

  • その後、@ ashosborne1によってすでに提供されているコードを使用してフォルダーにアクセスできます(申し訳ありませんが、このアイテムのリスト内でこのコードを正しく編集できなかったためです)。

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

これで、IDEを使用して何度でもテストを実行できます。mvn cleanを実行するまで。ターゲットフォルダをドロップします。

IDEを介してテストを実行する前に、テストフォルダー内にファイルを作成してmavenを初めて実行する必要があります。これらの手順がない場合、IDEでテストリソースを作成し、テストを記述してIDE経由でのみ実行すると、エラーが発生します。mvnを介してテストを実行すると、テストリソースがtarget / test-classes / teva / readmeにコピーされ、クラスローダーからアクセスできるようになります。

IDEに複数のMavenプロジェクトをインポートする必要があるのはなぜでしょうか。私にとって、主な動機の1つは、IDA関連のファイルをコードから遠ざけることです。まずIDEで新しいプロジェクトを作成します。これは偽のプロジェクトで、IDE関連のファイルを保持しているだけです。次に、既存のMavenプロジェクトをインポートします。これらのインポートされたプロジェクトに、IDEAファイルを元の偽のプロジェクトのみに保存するように強制します。その結果、コードにIDE関連のファイルが表示されません。SVNはそれらを表示すべきではありません(そのようなファイルを無視するようにsvn / gitを構成するように提案しないでください)。また、とても便利です。


こんにちはアレクサンダー、私はtarget / classesとsrc / main / resourceのリソースファイルに問題があります。最初にsrc / main / resourceにファイルがあり、プロジェクトをビルドした後、これらのファイルをtarget / classesにコピーします。そして、これから、getClass()。getClassLoader()。getResource(fileName)は、src / mainで作業したいのに、ターゲットフォルダーでのみ機能します。getResourceファイルのメカニズムについて説明するリンクをどこかに教えてもらえますか?リソースフォルダーの構成方法 Tks:D
HuyHómHỉnh2018年

2
@HuyHómHỉnh、私はそれをしないことをお勧めします。リソースファイルが配置されている特定の場所があり、その場所は他のすべての場所で認識されています。そのようなプロジェクトを維持することはより簡単です。あなたにとっても、それはより簡単になるでしょう、あなたはMavenプロジェクトの構造を理解する必要があるだけです。しかし、確かに、あなたは[デフォルトでのリソースの場所を設定することができますmaven.apache.org/plugins/maven-resources-plugin/examples/...
アレクサンドル・

HuyHómHỉnh@、またここに解決策を見てみます:stackoverflow.com/questions/23289098/...を しかし、あなたはSRC /メインリソースとして...それを避けるようにしてください設定するには、あなたが何かを間違った操作を行うようです。
Alexandr

うーん。何が問題になっているの.gitignoreですか?また、IDEAはテストの実行時にMavenを自動的に実行するように見えます(デフォルトでは、正しい作業ディレクトリが設定されます$MODULE_DIR$)。そのためmvn test、その前に手動で実行する必要はありません。MavenとIDEAの両方から、すべてが正常に機能し"src/test/resources/somefile.txt"ます。
Alex P.

5

私が使用する最も単純でクリーンなソリューションでは、テストクラスの名前がTestQuery1であり、次のようにフォルダーにresourcesディレクトリがあるとしますtest

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

TestQuery1do のURIを取得するには:

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

いずれかのファイルのURIを取得するにはTestQuery1、次のようにします。

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

1
心配ありません、実際にはあなたの助けをありがとう!良いことはあなたの答えを削除することです、私は質問を削除することができます。ええ、ここでもかなりイライラしていますが、とにかくありがとう!! こんばんは:)
Noor

1

一般的なケースでは、リソースフォルダーのファイルをテストに使用することはできません。その理由は、リソースフォルダー内のリソースファイルがjar内に格納されるためです。したがって、ファイルシステムに実際のパスはありません。

最も簡単な解決策は次のとおりです。

  1. リソースから一時フォルダーにファイルをコピーし、その一時ファイルへのパスを取得します。
  2. 一時パスを使用してテストを行います。
  3. 一時ファイルを削除します。

TemporaryFolderfrom JUnitを使用して、一時ファイルを作成し、テストの完了後に削除できます。guavaライブラリのクラスは、ファイルフォームのリソースフォルダーをコピーするために使用されます。

リソースフォルダー内のサブフォルダーを使用する場合など、リソースパスにgoodリード/を追加する必要がないことに注意してください。

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

以下を使用して、単体テストでHibernateにSpringを注入します。

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

フォルダーにhibernate.cfg.xmlプレゼントがない場合は、src/test/resourcesフォルダー内のプレゼントに自動的にフォールバックしsrc/main/resourcesます。


0

Fileオブジェクトで.getAbsolutePath()を使用します。

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

getFileはファイルインスタンスではなくStringインスタンスを返す
Almas Abdrazak

@AlmasAbdrazak GreatDantoneはgetFile()、ファイルのインスタンスを返すとは言っていません。彼はそれgetAbsolutePath()がFileオブジェクトのインスタンスで使用されていると言います。
メンティース

彼のコードによると@menteith、彼ははgetFile()、その後はgetFile上getAbsolutePath()()が、はgetFile()を呼び出すと、文字列を返し、あなたはStringオブジェクトにgetAbsolutePath()を呼び出すことはできません
アルマスAbdrazak

0

Springを使用すると、resourcesフォルダー(main / resourcesまたはtest / resources)から簡単に読み取ることができます。

たとえば、ファイルを作成します。 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);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.