【问题标题】:How to get the path of src/test/resources directory in JUnit?如何在 JUnit 中获取 src/test/resources 目录的路径?
【发布时间】:2015-04-24 18:27:08
【问题描述】:

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

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

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

【问题讨论】:

  • 出于好奇:你为什么想知道?
  • @fge 需要将它传递给被测对象,它使用它来加载文件
  • 直接文件访问你的资源目录是个坏主意。重构您的代码以在 Steam 上运行,或者让您的测试首先在 TemporaryFolder 中创建一个副本。
  • @OliverCharlesworth 我同意临时文件夹并一直使用org.junit.rules.TemporaryFolder...但是...从您需要知道的测试/资源中复制,呃,它的路径!
  • @mikerodent - 我认为的意思是:通过输入流读取资源,然后将其写入临时文件。

标签: java junit


【解决方案1】:

尝试使用ClassLoader 类:

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

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

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

【讨论】:

  • 这不一定是个好主意。如果资源在 Jar 中,这将导致悲伤。
  • @OliverCharlesworth 那么,遇到 jar 怎么办?
  • @AnmolSinghJaggi - 请参阅我在原始问题下方的评论:)
  • 使用此解决方案时,maven 构建失败
  • 文件名也可以
【解决方案2】:

你不需要弄乱类加载器。事实上,这是一个不好的习惯,因为类加载器资源在 jar 存档中时不是 java.io.File 对象。

Maven 会在运行测试前自动设置当前工作目录,所以你可以直接使用:

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

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

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

【讨论】:

  • 新文件("src/test/resources/fileXYZ");不管用。如果您只是将其放入 JUnit 测试中,则既不是来自 Eclipse 也不是来自 Maven。
  • 它在 Maven 中运行良好。在 Eclipse 中,您需要在测试运行程序中设置当前工作目录,但命令行 maven 会为您完成此操作。
  • 我不这么认为。如果您可以简单地执行“new File(getClass().getClassLoader().getResource("fileNameXYZ.xml")”而不需要任何设置,那么您为什么要这样做。在 Eclipse 和 Maven 中都没有。跨度>
  • 相反,您为什么不遵循构建实用程序的标准?特别是当它简化您的代码时。使用 IntelliJ 或 Maven,无需设置工作目录。这显然是最简单的解决方案,Eclipse 一如既往的痛苦。
  • 对于 IntelliJ 2014 版本,我仍然必须更改测试方法/类的运行/调试配置中的工作目录,正如@Steve C 提到的那样。
【解决方案3】:

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

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

在 Ubuntu 14.04 上使用 IntelliJ IDE 进行测试。 参考here

【讨论】:

    【解决方案4】:

    @Steve C 和@ashosborne1 提供的选项存在差异和限制。我相信它们必须被指定。

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

    • 1 仅通过 maven 而不是通过 IDE 运行测试时。
    • 2.1 何时通过 maven 或运行测试
    • 2.2 通过IDE,只有一个项目导入IDE。 (我使用“导入”术语,因为它在 IntelliJ IDEA 中使用。我认为 eclipse 的用户也会导入他们的 maven 项目)。这将起作用,因为您通过 IDE 运行测试时的工作目录与您的项目相同。
    • 3.1 何时通过 maven 运行测试或
    • 3.2 通过 IDE,并且在 IDE 中导入多个项目(如果您不是学生,通常会导入多个项目),AND 在通过 IDE 运行测试之前,您手动配置工作测试目录。该工作目录应该引用包含测试的导入项目。默认情况下,所有导入 IDE 的项目的工作目录只有一个。可能它只是IntelliJ IDEA 的限制,但我认为所有的IDE 都是这样工作的。而这种必须手动完成的配置,一点都不好。处理不同 maven 项目中存在的多个测试,但导入到一个大型“IDE”项目中,这迫使我们记住这一点,不要让您放松并从工作中获得乐趣。

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

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

      src/test/resources/teva/readme

      必须在 test 文件夹中创建文件,否则将无法正常工作。 Maven 会忽略空文件夹。

    • 至少一次通过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 项目,为什么要导入这么多复杂的东西?对我来说,主要动机之一是:让 IDA 相关文件远离代码。我首先在我的 IDE 中创建一个新项目。这是一个假项目,只是 IDE 相关文件的持有者。然后,我导入已经存在的 Maven 项目。我强制这些导入的项目仅将 IDEA 文件保留在我原来的假项目中。因此,我在代码中看不到与 IDE 相关的文件。 SVN 不应该看到它们(请不要将 svn/git 配置为忽略此类文件)。也很方便。

    【讨论】:

    • 嗨,Alexandr,我在 target/classes 和 src/main/resource 中的资源文件遇到了麻烦,你似乎只有一个人在谈论它。首先我在 src/main/resource 上有文件,在构建项目之后,它将这些文件复制到目标/类。由此,getClass().getClassLoader().getResource(fileName) 仅适用于目标文件夹,而我希望我适用于 src/main。你能给我链接解释一下getResource文件的机制吗?如何配置资源文件夹? Tks :D
    • @Huy Hóm Hỉnh,我建议不要这样做。恐怕你走错了方向。资源文件所在的某些地方,其他地方都是众所周知的。更容易维护这样的项目。即使对你来说它会更容易,你只需要了解 maven 项目的结构。但可以肯定的是,您可以使用 [maven.apache.org/plugins/maven-resources-plugin/examples/… 配置默认资源位置
    • @HuyHómHỉnh,也看看这里的解决方案:stackoverflow.com/questions/23289098/… 但是要将你的 src/main 配置为资源......尽量避免它,似乎你做错了什么。跨度>
    • 嗯。你能详细说明.gitignore 有什么问题吗?此外,IDEA 似乎在运行测试时会自动运行 Maven(并默认设置正确的工作目录,$MODULE_DIR$)。因此,在此之前无需手动运行mvn test,只需"src/test/resources/somefile.txt",Maven 和 IDEA 都可以正常运行。
    【解决方案5】:

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

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

    【讨论】:

    • 我们也可以像@Value("classpath: some_file.txt") private Resource someResource;一样使用@Value注入,然后在方法中someResource.getFile()获取文件。
    【解决方案6】:

    我会简单地使用 Java 7 中的 Path

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

    干净整洁!

    【讨论】:

    • 这个完全相同的代码可以在 Windows 上运行吗? Paths.get(...) 的 JavaDoc 建议(无论如何对我来说)它不会。
    • @SteveC 你可以使用File.separator 常量来构建用作路径的字符串
    • 我知道,但它很丑。相比之下,new File("src/test/resources") 在所有平台上都是正确的。
    • 为什么不直接使用Path resourceDirectory = Paths.get("src","test","resources");
    • 嗯,Paths.get("src", "test", "resources")Paths.get("src/test/resources") 对我来说在 Windows 10 上运行良好。我究竟做错了什么? =)
    【解决方案7】:

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

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

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

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

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

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

    【讨论】:

    • 不用担心,其实谢谢你的帮助!!好消息是删除您的答案,我可以删除问题。是的,在这里也很沮丧,但无论如何谢谢!晚上好:)
    【解决方案8】:

    在您的 File 对象上使用 .getAbsolutePath()。

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

    【讨论】:

    • getFile 返回字符串实例不是文件
    • @AlmasAbdrazak GreatDantone 并没有说getFile() 返回文件的实例。他说getAbsolutePath() 用于 File 对象的实例。
    • @menteith 根据他的代码,他在 getFile() 上调用 getFile() 然后 getAbsolutePath() 但 getFile() 返回 String 并且您不能在 String 对象上调用 getAbsolutePath()
    【解决方案9】:

    在您的单元测试中使用以下方法通过 Spring 注入 Hibernate:

    @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 文件夹中的那个。

    【讨论】:

      【解决方案10】:

      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() - 给你 target/test-classes 的 URI。
      2. resolve(Paths.get("somefile")) - 将 someFile 解析为 target/test-classes 文件夹。

      原始答案取自this

      【讨论】:

        【解决方案11】:

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

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

        1. 将文件从资源复制到临时文件夹并获取该临时文件的路径。
        2. 使用临时路径进行测试。
        3. 删除临时文件。

        JUnit 中的TemporaryFolder 可用于创建临时文件并在测试完成后将其删除。 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;
            }
        
        }
        

        【讨论】:

          【解决方案12】:

          使用 Spring,您可以轻松地从资源文件夹(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;
          }
          

          【讨论】:

            【解决方案13】:
            List<String> lines = Files.readAllLines(Paths.get("src/test/resources/foo.txt"));
            lines.forEach(System.out::println);
            

            【讨论】:

              【解决方案14】:

              有了 Spring,你可以这样使用:

              import org.springframework.core.io.ClassPathResource;
              
              // Don't worry when use a not existed directory or a empty directory
              // It can be used in @before
              String dir = new ClassPathResource(".").getFile().getAbsolutePath()+"/"+"Your Path";
              

              【讨论】:

                【解决方案15】:

                你可以通过它到达你所在的地方

                new File(".").getAbsolutePath()
                

                然后你可以导出到 src/test/resources 的路径
                通常只是

                new File("src/test/resources")
                

                【讨论】:

                  【解决方案16】:

                  哇,还没有正确答案!

                  MyClass.class.getResource("/somefile");
                  MyClass.class.getResourceAsStream("/somefile");
                  

                  https://javachannel.org/posts/how-to-access-static-resources/

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2013-05-11
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多