Why Can't I access src/test/resources in Junit test run with Maven?
I am having a problems running the following code:
configService.setMainConfig("src/test/resources/MainConfig.xml");
From within a Junit @Before method.
Is this the way Maven builds out its target folder?
Solution 1:
Access MainConfig.xml
directly. The src/test/resources
directory contents are placed in the root of your CLASSPATH.
More precisely: contents of src/test/resources
are copied into target/test-classes
, so if you have the following project structure:
.
└── src
└── test
├── java
│ └── foo
│ └── C.java
└── resources
├── a.xml
└── foo
└── b.xml
It will result with the following test CLASSPATH contents:
/foo/C.class
/a.xml
/foo/b.xml
To actually access the files from Java source, use
getClass().getResource("/MainConfig.xml").getFile()
.
Solution 2:
I ran into the same problem today and I have found some solutions.
First, here is my file structure:
.
└── src
│ └── test
│ ├── java
│ │ └── mypackage
│ │ └── MyClassTest.java
│ └── resources
│ └── image.jpg
└── target
└── test-classes
├── image.jpg
└── mypackage
└── MyClassTest.class
What is not working: (Java 11 synthax)
var imgFile = new File("image.jpg"); // I was expecting that Junit could find the file.
var absPath = file.getAbsolutePath(); // /home/<user>/../<project-root>/image.jpg
var anyFileUnderThisPath = file.exists(); // false
What we can notice is that the absolute path does not point at all on my image! But if I had an image under at the project-root, then it would have worked.
Solution 1: Paths (introduced in Java 7)
var relPath = Paths.get("src", "test", "resources", "image.jpg"); // src/test/resources/image.jgp
var absPath = relPath.toFile().getAbsolutePath(); // /home/<user>/../<project-root>/src/test/resources/image.jpg
var anyFileUnderThisPath = new File(absPath).exists(); // true
As we can see, it points on the right file.
Solution 2: ClassLoader
var classLoader = getClass().getClassLoader();
var url = classLoader.getResource("image.jpg"); // file:/home/<user>/../<project-root>/target/test-classes/image.jpg
var file = new File(url.getFile()); // /home/<user>/../<project-root>/target/test-classes/image.jpg
var anyFileUnderThisPath = file.exists(); // true
Note that now the file is searched under the target directory! and it works.
Solution 3: File (Adaptation of the non-working example)
var absPath = new File("src/test/resources/image.jpg").getAbsolutePath();
var var anyFileUnderThisPath = new File(absPath).exists(); // true
Which works also after taking the absolute path and putting src/test/resources/
as prefix.
Summary
All three solutions works but having to put src/test/resources/
is, in my own opinion not elegant, and this is why I would prefer the 2nd solution (ClassLoader
).
Sources:
- Read file and resource in junit test
- Java read a file from resources folder
Solution 3:
I guess setMainConfig
expects the path of a resource, that it will load using the ClassLoader, and not a relative file path. It would help if you linked to the javadoc of this mysterious configService.setMainConfig
method.
If my guess is correct, then the path should just be MainConfig.xml. Mave copies the contents of src/test/resources
to the target/test-classes
(IIRC) folder. And this test-classes folder is in the classpath of the unit tests.