如何在 Maven 和 Intellij 之间处理 Junits 中的相对路径

Posted

技术标签:

【中文标题】如何在 Maven 和 Intellij 之间处理 Junits 中的相对路径【英文标题】:How to deal with relative path in Junits between Maven and Intellij 【发布时间】: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

有办法解决吗?

【问题讨论】:

谢谢!这是我的确切问题 【参考方案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。我已经浪费了很多时间试图弄清楚发生了什么...... 谢谢我知道这些东西,但我需要检索一个不能在类路径中的文件,因为它的路径是在某些参数中配置的。我真的需要一个相对路径的解决方案。

以上是关于如何在 Maven 和 Intellij 之间处理 Junits 中的相对路径的主要内容,如果未能解决你的问题,请参考以下文章

intellij Project make 和 Maven Compile 之间的区别?

如何在 IntelliJ IDEA 中创建 JavaFX Maven 项目?

Intellij 处理混合项目(maven+gradle)

在 IntelliJ 中,如何调试 Maven 测试目标?

如何在 IntelliJ 中更改 Maven 的 Java 版本?

如何在 Intellij 中创建 Maven 多模块项目?