JUnit中如何获取src/test/resources目录的路径?
How to get the path of src/test/resources directory in JUnit?
我知道我可以从 src/test/resources 加载一个文件:
getClass().getResource("somefile").getFile()
但是我怎样才能得到 src/test/resources 目录 的完整路径,即我不想加载文件,我只想知道路径目录的?
尝试使用 ClassLoader
class:
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("somefile").getFile());
System.out.println(file.getAbsolutePath());
一个ClassLoader
负责加载classes。每个 class 都引用了一个 ClassLoader
。此代码 returns 来自资源目录的 File
。在其上调用 getAbsolutePath()
returns 其绝对 Path
.
ClassLoader
的 Javadoc:http://docs.oracle.com/javase/7/docs/api/java/lang/ClassLoader.html
您不需要弄乱 class 加载器。事实上,这是一个坏习惯,因为 class 加载程序资源在 jar 存档中时 不是 java.io.File 对象。
Maven 在 运行 测试之前自动设置当前工作目录,所以你可以只使用:
File resourcesDirectory = new File("src/test/resources");
resourcesDirectory.getAbsolutePath()
将 return 是您真正需要的正确值。
如果您希望测试通过文件系统访问数据,我建议创建一个 src/test/data
目录。这让你清楚地知道你在做什么。
我有一个使用 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());
...
}
使用 IntelliJ IDE 在 Ubuntu 14.04 上测试。
参考 here.
备注
前缀 /
符号是必要的,因为 Class.getResource(String)
不一定会与 FileNotFoundException
.
一起显示整个文件路径(丢失)
@Steve C 和@ashosborne1 提供的选项存在差异和限制。我相信它们必须被指定。
我们什么时候可以使用:File resourcesDirectory = new File("src/test/resources");
?
- 1 当测试将 运行 仅通过 maven 而不是通过 IDE.
- 2.1 当测试将通过 Maven 或
运行
- 2.2 via IDE 并且只有一个项目导入到 IDE。 (我使用“导入”术语,因为它在 IntelliJ IDEA 中使用。我认为 eclipse 的用户也导入他们的 maven 项目)。这将起作用,因为当您通过 IDE 进行 运行 测试时,工作目录与您的项目相同。
- 3.1 当测试将通过 Maven 或
运行
- 3.2 via IDE,并且导入了多个项目到IDE(不是学生的时候,一般会导入几个项目),AND 在通过 IDE 进行 运行 测试之前,您需要为测试手动配置工作目录。该工作目录应引用包含测试的导入项目。默认情况下,导入到 IDE 中的所有项目的工作目录只有一个。可能这只是
IntelliJ IDEA
的限制,但我认为所有 IDE 都是这样工作的。而这种必须手动完成的配置,一点也不好。使用不同 maven 项目中存在的多个测试,但导入到一个大的“IDE”项目中,迫使我们记住这一点,不要放松并从工作中获得乐趣。
@ashosborne1 提供的解决方案(我个人更喜欢这个)需要 2 个额外的要求,必须在 运行 测试之前完成。以下是使用此解决方案的步骤列表:
在“src/test/resources/”中创建一个测试文件夹(“teva”)和文件(“readme”):
src/test/resources/teva/自述文件
必须在test文件夹下创建文件,否则无法运行。 Maven 忽略空文件夹。
至少一次通过 mvn clean install
构建项目。它也会 运行 测试。通过 maven 运行 只有你的测试 class/method 可能就足够了,而无需构建整个项目。因此,您的测试资源将被复制到 test-类,这是一个路径: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。它将删除目标文件夹。
在测试文件夹中创建文件并运行第一次使用 maven,在通过 IDE 进行 运行 测试之前,需要一些步骤。如果没有这些步骤,如果您只是在 IDE 中创建测试资源,然后仅通过 IDE 编写测试并 运行 它,您将收到错误消息。 运行 通过 mvn 进行的测试将测试资源复制到 target/test-classes/teva/readme 并且类加载器可以访问它们。
你可能会问,为什么我需要在IDE中导入多个maven项目,为什么要搞那么多复杂的东西?对我来说,主要动机之一是:让与 IDA 相关的文件远离代码。我首先在 IDE 中创建一个新项目。这是一个假项目,只是 IDE 相关文件的持有者。然后,我导入已经存在的 Maven 项目。我强制这些导入的项目只在我原来的假项目中保留 IDEA 文件。因此,我在代码中看不到 IDE 相关文件。 SVN 不应该看到它们(请不要提供配置 svn/git 来忽略这些文件)。而且还是很方便的。
如果是 spring 项目,我们可以使用下面的代码从 src/test/resource 文件夹中获取文件。
File file = ResourceUtils.getFile(this.getClass().getResource("/some_file.txt"));
我会简单地使用 Java 7
中的 Path
Path resourceDirectory = Paths.get("src","test","resources");
干净整洁!
我使用的最简单干净的解决方案,假设测试 class 的名称是 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");
在您的文件对象上使用 .getAbsolutePath()。
getClass().getResource("somefile").getFile().getAbsolutePath()
使用以下命令在您的单元测试中使用 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
文件夹中的那个。
src/test/resources
中的所有内容都被复制到 target/test-classes
文件夹中。因此,要在 Maven 构建期间从测试资源中获取文件,您必须从 test-classes
文件夹中加载它,如下所示:
Paths.get(
getClass().getProtectionDomain().getCodeSource().getLocation().toURI()
).resolve(
Paths.get("somefile")
).toFile()
细分:
getClass().getProtectionDomain().getCodeSource().getLocation().toURI()
- 给你 target/test-classes
. 的 URI
resolve(Paths.get("somefile"))
- 将 someFile
解析为 target/test-classes
文件夹。
原答案取自this
在常见情况下,您不能使用资源文件夹中的文件进行测试。原因是资源文件夹中的资源文件存储在一个jar 中。所以他们在文件系统中没有真正的路径。
最简单的解决方案可以是:
- 将文件从资源复制到临时文件夹并获取该临时文件的路径。
- 使用临时路径进行测试。
- 删除临时文件。
TemporaryFolder
from JUnit
可用于创建临时文件并在测试完成后将其删除。 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;
}
}
使用 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;
}
List<String> lines = Files.readAllLines(Paths.get("src/test/resources/foo.txt"));
lines.forEach(System.out::println);
有了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";
你可以通过
到达你所在的地方
new File(".").getAbsolutePath()
然后你可以推导出 src/test/resources
的路径
通常只是
new File("src/test/resources")
哇正确答案还没出来!
MyClass.class.getResource("/somefile");
MyClass.class.getResourceAsStream("/somefile");
https://javachannel.org/posts/how-to-access-static-resources/
我知道我可以从 src/test/resources 加载一个文件:
getClass().getResource("somefile").getFile()
但是我怎样才能得到 src/test/resources 目录 的完整路径,即我不想加载文件,我只想知道路径目录的?
尝试使用 ClassLoader
class:
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("somefile").getFile());
System.out.println(file.getAbsolutePath());
一个ClassLoader
负责加载classes。每个 class 都引用了一个 ClassLoader
。此代码 returns 来自资源目录的 File
。在其上调用 getAbsolutePath()
returns 其绝对 Path
.
ClassLoader
的 Javadoc:http://docs.oracle.com/javase/7/docs/api/java/lang/ClassLoader.html
您不需要弄乱 class 加载器。事实上,这是一个坏习惯,因为 class 加载程序资源在 jar 存档中时 不是 java.io.File 对象。
Maven 在 运行 测试之前自动设置当前工作目录,所以你可以只使用:
File resourcesDirectory = new File("src/test/resources");
resourcesDirectory.getAbsolutePath()
将 return 是您真正需要的正确值。
如果您希望测试通过文件系统访问数据,我建议创建一个 src/test/data
目录。这让你清楚地知道你在做什么。
我有一个使用 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());
...
}
使用 IntelliJ IDE 在 Ubuntu 14.04 上测试。 参考 here.
备注
前缀 /
符号是必要的,因为 Class.getResource(String)
不一定会与 FileNotFoundException
.
@Steve C 和@ashosborne1 提供的选项存在差异和限制。我相信它们必须被指定。
我们什么时候可以使用:File resourcesDirectory = new File("src/test/resources");
?
- 1 当测试将 运行 仅通过 maven 而不是通过 IDE.
- 2.1 当测试将通过 Maven 或 运行
- 2.2 via IDE 并且只有一个项目导入到 IDE。 (我使用“导入”术语,因为它在 IntelliJ IDEA 中使用。我认为 eclipse 的用户也导入他们的 maven 项目)。这将起作用,因为当您通过 IDE 进行 运行 测试时,工作目录与您的项目相同。
- 3.1 当测试将通过 Maven 或 运行
- 3.2 via IDE,并且导入了多个项目到IDE(不是学生的时候,一般会导入几个项目),AND 在通过 IDE 进行 运行 测试之前,您需要为测试手动配置工作目录。该工作目录应引用包含测试的导入项目。默认情况下,导入到 IDE 中的所有项目的工作目录只有一个。可能这只是
IntelliJ IDEA
的限制,但我认为所有 IDE 都是这样工作的。而这种必须手动完成的配置,一点也不好。使用不同 maven 项目中存在的多个测试,但导入到一个大的“IDE”项目中,迫使我们记住这一点,不要放松并从工作中获得乐趣。
@ashosborne1 提供的解决方案(我个人更喜欢这个)需要 2 个额外的要求,必须在 运行 测试之前完成。以下是使用此解决方案的步骤列表:
在“src/test/resources/”中创建一个测试文件夹(“teva”)和文件(“readme”):
src/test/resources/teva/自述文件
必须在test文件夹下创建文件,否则无法运行。 Maven 忽略空文件夹。
至少一次通过
mvn clean install
构建项目。它也会 运行 测试。通过 maven 运行 只有你的测试 class/method 可能就足够了,而无需构建整个项目。因此,您的测试资源将被复制到 test-类,这是一个路径: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。它将删除目标文件夹。
在测试文件夹中创建文件并运行第一次使用 maven,在通过 IDE 进行 运行 测试之前,需要一些步骤。如果没有这些步骤,如果您只是在 IDE 中创建测试资源,然后仅通过 IDE 编写测试并 运行 它,您将收到错误消息。 运行 通过 mvn 进行的测试将测试资源复制到 target/test-classes/teva/readme 并且类加载器可以访问它们。
你可能会问,为什么我需要在IDE中导入多个maven项目,为什么要搞那么多复杂的东西?对我来说,主要动机之一是:让与 IDA 相关的文件远离代码。我首先在 IDE 中创建一个新项目。这是一个假项目,只是 IDE 相关文件的持有者。然后,我导入已经存在的 Maven 项目。我强制这些导入的项目只在我原来的假项目中保留 IDEA 文件。因此,我在代码中看不到 IDE 相关文件。 SVN 不应该看到它们(请不要提供配置 svn/git 来忽略这些文件)。而且还是很方便的。
如果是 spring 项目,我们可以使用下面的代码从 src/test/resource 文件夹中获取文件。
File file = ResourceUtils.getFile(this.getClass().getResource("/some_file.txt"));
我会简单地使用 Java 7
中的Path
Path resourceDirectory = Paths.get("src","test","resources");
干净整洁!
我使用的最简单干净的解决方案,假设测试 class 的名称是 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");
在您的文件对象上使用 .getAbsolutePath()。
getClass().getResource("somefile").getFile().getAbsolutePath()
使用以下命令在您的单元测试中使用 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
文件夹中的那个。
src/test/resources
中的所有内容都被复制到 target/test-classes
文件夹中。因此,要在 Maven 构建期间从测试资源中获取文件,您必须从 test-classes
文件夹中加载它,如下所示:
Paths.get(
getClass().getProtectionDomain().getCodeSource().getLocation().toURI()
).resolve(
Paths.get("somefile")
).toFile()
细分:
getClass().getProtectionDomain().getCodeSource().getLocation().toURI()
- 给你target/test-classes
. 的 URI
resolve(Paths.get("somefile"))
- 将someFile
解析为target/test-classes
文件夹。
原答案取自this
在常见情况下,您不能使用资源文件夹中的文件进行测试。原因是资源文件夹中的资源文件存储在一个jar 中。所以他们在文件系统中没有真正的路径。
最简单的解决方案可以是:
- 将文件从资源复制到临时文件夹并获取该临时文件的路径。
- 使用临时路径进行测试。
- 删除临时文件。
TemporaryFolder
from JUnit
可用于创建临时文件并在测试完成后将其删除。 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;
}
}
使用 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;
}
List<String> lines = Files.readAllLines(Paths.get("src/test/resources/foo.txt"));
lines.forEach(System.out::println);
有了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";
你可以通过
到达你所在的地方new File(".").getAbsolutePath()
然后你可以推导出 src/test/resources
的路径
通常只是
new File("src/test/resources")
哇正确答案还没出来!
MyClass.class.getResource("/somefile");
MyClass.class.getResourceAsStream("/somefile");
https://javachannel.org/posts/how-to-access-static-resources/