关于java:如何在JUnit中获取src / test / resources目录的路径?

How to get the path of src/test/resources directory in JUnit?

我知道我可以从src/test/resources加载文件:

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

但是我怎样才能获得到src/test/resources目录的完整路径,也就是说,我不想加载文件,我只想知道目录的路径?


你不需要和类加载器搞混。事实上,这是一个坏习惯,因为类装入器资源在JAR存档中时不是java.io.file对象。

Maven会在运行测试之前自动设置当前工作目录,因此您只需使用:

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

如果您真的需要,resourcesDirectory.getAbsolutePath()将返回正确的值。

如果希望测试通过文件系统访问数据,我建议创建一个src/test/data目录。这就清楚了你在做什么。


尝试使用ClassLoader类:

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

ClassLoader负责类中的加载。每个类都有一个对ClassLoader的引用。此代码从资源目录返回一个File。调用getAbsolutePath()返回其绝对值Path

用于EDOCX1的javadoc〔0〕:http://docs.oracle.com/javase/7/docs/api/java/lang/classloader.html


我将简单地使用Java 7中的EDCOX1 4

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

干净整洁!


如果它是一个Spring项目,我们可以使用下面的代码从src/test/resource文件夹中获取文件。

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

我有一个使用JUnit4.12和Java8的Maven3项目。为了获得src/test/resources下名为myxml.xml的文件的路径,我从测试用例中执行此操作:

1
2
3
4
5
6
7
@Test
public void testApp()
{
    File inputXmlFile = new File(this.getClass().getResource("/myxml.xml").getFile());
    System.out.println(inputXmlFile.getAbsolutePath());
    ...
}

使用Intellij IDE在Ubuntu 14.04上测试。参考这里。


src/test/resources中的所有内容复制到target/test-classes文件夹中。因此,要在Maven构建期间从测试资源中获取文件,您必须从test-classes文件夹中加载它,如下所示:

1
2
3
4
5
Paths.get(
    getClass().getProtectionDomain().getCodeSource().getLocation().toURI()
).resolve(
    Paths.get("somefile")
).toFile()

发生故障:

  • getClass().getProtectionDomain().getCodeSource().getLocation().toURI()—把uri给target/test-classes
  • resolve(Paths.get("somefile"))—将someFile解析为target/test-classes文件夹。
  • 原来的安华是从这个


    @steve c和@ashosborne1提供的选项存在差异和限制。我相信,必须具体说明。

    什么时候可以使用:File resourcesDirectory = new File("src/test/resources");

    • 1当测试只通过maven而不是通过ide运行时。
    • 2.1通过Maven或
    • 2.2通过IDE,只有一个项目导入到IDE中。(我使用"导入"术语,因为它用于Intellij思想。我认为Eclipse的用户也会导入他们的Maven项目)。这将有效,因为通过IDE运行测试时的工作目录与项目相同。
    • 3.1通过Maven或
    • 3.2通过IDE,并将多个项目导入到IDE中(当您不是学生时,通常导入多个项目),在通过IDE运行测试之前,您可以手动配置测试的工作目录。该工作目录应该引用包含测试的导入项目。默认情况下,导入到IDE中的所有项目的工作目录只有一个。可能这只是IntelliJ IDEA的限制,但我认为所有的IDE都是这样工作的。而且这种必须手动完成的配置根本不好。使用不同Maven项目中存在的几个测试,但导入到一个大型的"IDE"项目中,迫使我们记住这一点,并且不允许放松和从您的工作中获得乐趣。

    @ashosborne1(我个人更喜欢这个)提供的解决方案需要2个额外的要求,这些要求必须在运行测试之前完成。以下是使用此解决方案的步骤列表:

    • 在"src/test/resources/"中创建一个测试文件夹("teva")和文件("readme"):

      src/test/resources/teva/readme文件

      文件必须在测试文件夹中创建,否则将不起作用。Maven忽略空文件夹。

    • 至少一次通过mvn clean install构建项目。它还将运行测试。在不构建整个项目的情况下,只通过Maven运行测试类/方法可能就足够了。因此,您的测试资源将被复制到测试类中,下面是一条路径:target/test-classes/teva/readme
    • 之后,您可以使用@ashosborne1提供的代码访问文件夹(很抱歉,我无法在项目列表中正确编辑此代码):
    1
    2
    3
    public static final String TEVA_FOLDER ="teva"; ...
    URL tevaUrl = YourTest.class.getClassLoader().getResource(TEVA_FOLDER);
    String tevaTestFolder = new File(tevaUrl.toURI()).getAbsolutePath();

    现在,您可以通过IDE运行您的测试任意多次。直到你跑干净。它将删除目标文件夹。

    在测试文件夹中创建文件并在通过IDE运行测试之前首次运行maven是必需的步骤。如果没有这些步骤,如果您只是在您的IDE中创建测试资源,然后编写测试并只通过IDE运行它,您将得到一个错误。通过MVN运行测试会将测试资源复制到目标/测试类/teva/readme中,并且类加载器可以访问这些资源。

    您可能会问,为什么我需要在IDE中导入多个Maven项目,为什么要导入这么多复杂的东西?对我来说,主要的动机之一是:使与IDA相关的文件远离代码。我首先在我的IDE中创建一个新项目。这是一个伪造的项目,它只是一个与IDE相关的文件的持有者。然后,我导入已经存在的Maven项目。我强制这些导入的项目只在我原来的伪项目中保留想法文件。因此,代码中没有与IDE相关的文件。SVN不应该看到它们(请不要提供将SVN/Git配置为忽略这些文件)。而且很方便。


    我使用的最简单、干净的解决方案是,假设测试类的名称是TestQuery1,并且您的test文件夹中有一个resources目录,如下所示:

    1
    2
    3
    4
    5
    6
    ├── java
       └── TestQuery1.java
    └── resources
        └── TestQuery1
            ├── query.json
            └── query.rq

    要获取TestQuery1的URI,请执行以下操作:

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

    要获取某个文件TestQuery1的URI,请执行以下操作:

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


    在常见情况下,不能使用资源文件夹中的文件进行测试。原因是资源文件夹中的资源文件存储在JAR中。所以他们在文件系统中没有真正的路径。

    最简单的解决方案可以是:

  • 将文件从资源复制到临时文件夹,并获取该临时文件的路径。
  • 使用临时路径进行测试。
  • 删除临时文件。
  • 来自JUnitTemporaryFolder可用于创建临时文件,并在测试完成后将其删除。guava库中的类用于复制文件表单资源文件夹。

    请注意,如果我们使用resources文件夹中的子文件夹,如goodone,则不必向资源路径添加前导/

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    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;
        }

    }

    在单元测试中,使用以下方法将Hibernate与Spring一起注入:

    1
    2
    3
    4
    5
    6
    7
    @Bean
    public LocalSessionFactoryBean getLocalSessionFactoryBean() {
        LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
        localSessionFactoryBean.setConfigLocation(new ClassPathResource("hibernate.cfg.xml"));
        localSessionFactoryBean.setPackagesToScan("com.example.yourpackage.model");
        return localSessionFactoryBean;
    }

    如果您的src/test/resources文件夹中没有hibernate.cfg.xml,它将自动返回到src/main/resources文件夹中。


    对文件对象使用.getAbsolutePath()。

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