【问题标题】:How to deal with relative path in Junits between Maven and Intellij如何在 Maven 和 Intellij 之间处理 Junits 中的相对路径
【发布时间】:2011-08-04 00:16:49
【问题描述】:

我有一个带有模块的 maven 项目

/myProject
pom.xml
    /myModule
    pom.xml
       /foo
       bar.txt

考虑myModule中的一个Junit,它需要打开bar.txt,maven的basedir就是模块目录。

所以打开文件bar.txt

  new File("foo/bar.txt")

当您在 intellij 中启动相同的 junit 时执行 mvn test BUT 时,这很有效,因为 Intellij 在项目目录中设置了 basedir,而不是模块目录。

Intellij 尝试打开 myProject/foo/bar.txt 而不是 myProject/myModule/foo/bar.txt

有办法解决吗?

【问题讨论】:

  • 谢谢!这是我的确切问题

标签: java maven-2 junit intellij-idea


【解决方案1】:

如果您将项目文件 (.idea) 保存在与源代码相同的目录中,则来自 @tbruyelle 的解决方案有效。如果您选择 Keep Project files in ... 在不同的位置,则 $MODULE_DIR$ 会尝试在工作区目录中查找并且找不到路径。这看起来像是 IntelliJ 上的一个错误,希望他们尽快修复它。

解决方法: 您可以在工作目录中指定maven模块的绝对/相对路径

$MODULE_DIR$/../master/mavenmodule1

$MODULE_DIR$: points to workspace directory
../: relative path to source code
master: root directory of your source code
mavenmodule1: maven module name / directory name of the child module.

对于多模块 maven 项目,您别无选择,您需要有不同的运行配置指向该模块。我希望有另一个变量只指向 $MAVEN_MODULE$ ($MODULE_DIR$/../master/$MAVEN_MODULE$),这样我们就可以对所有模块使用这个配置。对于上面的示例,$MAVEN_MODULE$ 将替换为 mavenmodule1

【讨论】:

    【解决方案2】:

    您可以在运行/调试配置窗口中指定测试运行器的工作目录:

    【讨论】:

      【解决方案3】:

      受纪尧姆启发的解决方案:

      Run->Edit configuration->Defaults->JUnit->Working directory 中设置$MODULE_DIR$ 的值,Intellij 将像 Maven 一样设置所有junit 中的相对路径。

      【讨论】:

      • 完美!你不知道这花费了我和我的团队多少时间,这记录在哪里?
      • 无处可去,但现在新版本的 Intellij 建议 MODULE_DIR 文本字段的 MODULE_DIR
      • 类加载比文件好得多...使用文件系统是邪恶的
      • 使用文件系统是邪恶的?你认为最终的文件来自哪里???在某些情况下,例如当使用 C.I.服务器,您可能希望指定要在工件中不存在的测试用例中使用的源配置文件。请告诉我我应该如何在不使用邪恶文件系统的情况下与他们联系。谢谢。
      • 请注意,这会改变您的默认 JUnit 启动配置。因此,它不会改变您已经创建的任何配置。如果此解决方案不适合您,请仔细检查您实际使用的配置以及它是否正确继承了此值。
      【解决方案4】:

      如果您想保留您的代码,您可以尝试更改运行/调试配置中的工作目录(组合框中的第一个条目可以访问您要运行的内容) 将此设置为您的模块根目录。 但更喜欢其他建议的方法:

      ClassLoader.getSystemResourceAsStream(youPath) 
      

      或者我的首选:

      getClass.getResource(youPath)
      

      getClass.getResourceAsStream(youPath)
      

      路径中的前导“/”表示项目的工作目录,而没有“/”表示当前类的相对目录。

      我将最后一个解决方案用于我的测试:我将我的测试数据资源放在与测试源相同的包级别,或者放在子目录中以避免过于混乱的包。

      这样我可以进行简单的调用,无需复杂的路径,也无需处理工作目录:

      project-root  
        - module A  
          - src  
            - test
              - rootfile.txt  
              - my-complicated-package-naming-root
                - mypackage
                  - Test.java
                  - testResource.xml  
      

      我可以通过这种方式获取文件:

      final URL rootfile= Test.class.getResource("/rootfile.txt");
      final URL testResource= Test.class.getResource("testResource.xml");
      

      【讨论】:

      • 我将 junit 工作目录设置为 $MODULE_DIR$ 并且它按预期工作。不幸的是,在默认的 junit 配置中不能使用这个变量!真可惜……
      • $MODULE_DIR$ 在默认的 junit 配置中不建议使用,但您可以强制“工作配置”字段中的值 avec 它有效!
      • @iangreen:你真的确定是这样吗?你介意引用文档吗?
      【解决方案5】:

      a) 不要使用文件,使用 InputStreams。通过

      获取您的InputStream
      ClassLoader.getSystemResourceAsStream("foo/bar.xml")
      

      大多数处理文件的 API 也对 InputStreams 感到满意。

      b) 不要使用 foo 目录,使用 maven 和您的 IDE 都知道的目录(即将它们放在 src/main/resourcessrc/test/resources 中,因此它们位于类路径中)

      c) 如果您的 API 绝对需要 File,而不是 InputStream,您仍然可以这样做

      new File(ClassLoader.getSystemResource("foo/bar.xml").toURI())
      

      【讨论】:

      • 如果您在项目中使用 groovy,请小心:ClassLoader.getSystemResourceAsStream 可能会停止工作(始终返回 null),因为 intellij 开始使用命令行包装器/动态代理。请参阅禁用此功能jguru.com/faq/view.jsp?EID=1533847。我已经浪费了很多时间试图弄清楚发生了什么......
      • 谢谢我知道这些东西,但我需要检索一个不能在类路径中的文件,因为它的路径是在某些参数中配置的。我真的需要一个相对路径的解决方案。
      猜你喜欢
      • 2012-09-23
      • 2014-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-07
      • 2011-01-29
      • 2018-06-17
      • 2015-03-27
      相关资源
      最近更新 更多