Java 如何处理Junits中Maven和Intellij之间的相对路径
我有一个带模块的maven项目Java 如何处理Junits中Maven和Intellij之间的相对路径,java,maven-2,junit,intellij-idea,Java,Maven 2,Junit,Intellij Idea,我有一个带模块的maven项目 /myProject pom.xml /myModule pom.xml /foo bar.txt 考虑myModule中的Junit,它需要打开bar.txt,在maven中,basedir是模块目录 因此,要打开文件bar.txt: 当您执行mvn测试时,这一点很好,但是当您在intellij中启动同一个junit时,它会失败,因为intellij在项目目录而不是模块目录中设置basedir Intellij尝试打
/myProject
pom.xml
/myModule
pom.xml
/foo
bar.txt
考虑myModule中的Junit,它需要打开bar.txt,在maven中,basedir是模块目录
因此,要打开文件bar.txt:
当您执行mvn测试时,这一点很好,但是当您在intellij中启动同一个junit时,它会失败,因为intellij在项目目录而不是模块目录中设置basedir
Intellij尝试打开myProject/foo/bar.txt
而不是myProject/myModule/foo/bar.txt
有没有办法解决这个问题?a)不要使用文件,使用InputStreams。通过获取您的InputStream
ClassLoader.getSystemResourceAsStream("foo/bar.xml")
大多数处理文件的API也喜欢InputStreams
b) 不要使用foo
目录,使用maven和IDE都知道的目录(即将它们放在src/main/resources
或src/test/resources
中,这样它们就在类路径上)
c) 如果您的API绝对需要文件
,而不是输入流
,您仍然可以这样做
new File(ClassLoader.getSystemResource("foo/bar.xml").toURI())
如果要保留代码,可以尝试更改运行/调试配置中的工作目录(组合框中的第一个条目提供对要运行的内容的访问权限)
将其设置为模块根目录。
但更喜欢其他建议的方法:
ClassLoader.getSystemResourceAsStream(youPath)
或者我的首选:
getClass.getResource(youPath)
或
路径中的前导“/”表示项目的工作目录,而no“/”表示当前类的相对目录
我在测试中使用最后一种解决方案:我将测试数据资源放在与测试源相同的包级别,或者放在子目录中,以避免包太乱
这样我就可以进行简单的调用,而无需复杂的路径,也无需处理工作目录:
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");
受纪尧姆启发的解决方案:
在Run->Edit configuration->Defaults->JUnit->Working directory
中设置值$MODULE\u DIR$
,Intellij将像Maven一样设置所有JUnit中的相对路径。您可以在运行/调试配置窗口中为测试运行程序指定工作目录:
如果您将项目文件(.idea)保存在与源代码相同的目录中,@tbruyelle提供的解决方案可以工作。如果选择将项目文件保存在其他位置的…,则$MODULE_DIR$正试图在工作区目录中查找,并且找不到路径。这看起来像IntelliJ上的一个bug,希望他们能尽快修复
解决方法:
您可以在工作目录中指定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如果您在项目中使用groovy,请小心:ClassLoader.getSystemResourceAsStream可能会停止工作(返回总是null),因为intellij开始使用命令行包装器/动态代理。请参阅以禁用此功能。我花了很多时间试图弄清楚发生了什么…谢谢,我知道这些东西,但我需要检索一个不能在类路径中的文件,因为它的路径在某些参数中配置。我真的需要一个具有相对路径的解决方案。我将junit工作目录设置为$MODULE_DIR$,它可以按预期工作。不幸的是,在默认junit配置中不可能使用这个变量!真遗憾…$MODULE_DIR$在默认junit配置中不建议使用,但是您可以在“working configuration”(工作配置)字段中强制使用它@伊恩格林:你真的确定是这样吗?你介意引用文档吗?太好了!你不知道这花费了我和我的团队多少时间,这是在哪里记录的?没有,但现在Intellij的新版本建议工作目录的模块目录值文本字段类加载比文件加载好得多。。。使用文件系统是邪恶的使用文件系统是邪恶的?你认为最终的文件来自哪里???在某些情况下,例如,当使用C.I.服务器时,您可能希望指定在您的测试用例中使用的源配置文件,而这些文件在您的工件中并不存在。请告诉我,如果不使用邪恶的文件系统,我应该如何找到他们。谢谢。请注意,这会改变默认的JUnit启动配置。因此,它不会改变您已经创建的任何配置。如果此解决方案不适用于您,请仔细检查您实际使用的配置以及它是否正确继承了此值。谢谢!这正是我的问题
final URL rootfile= Test.class.getResource("/rootfile.txt");
final URL testResource= Test.class.getResource("testResource.xml");
$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.