Why Can't I access src/test/resources in Junit test run with Maven?
Asked Answered
E

3

50

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?

Erasmo answered 30/9, 2011 at 16:29 Comment(0)
E
73

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().

Extracanonical answered 30/9, 2011 at 16:37 Comment(4)
Thanks for this consise answer. You are indeed correct that the file can be seen under /target/test-classes. I still cannot ref it from my code however. Have tried all sorts of combinations: 'configService.setMainConfig("MainConfig.xml"); ' 'configService.setMainConfig("target/test-classes/MainConfig.xml"); ' configService.setMainConfig("classpath:MainConfig.xml"); etc etcErasmo
Try getClass().getResource("/MainConfig.xml").getFile()Extracanonical
If you are using Tycho and eclipse-plugin as packaging type, don't forget to aadd src/test/resources in build.properties file.Chayachayote
Thank you, but i run my junit in jenkins its failing, for some reason the files from src/test/resource is getting copied to /target/classes instead of /target/test-classesExpose
I
5

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:

Incongruent answered 2/8, 2019 at 12:31 Comment(0)
E
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.

Estreat answered 30/9, 2011 at 16:38 Comment(1)
Thanks for this. your logic is correct(see comment above) but unfortunatley I still cannot get this to workErasmo

© 2022 - 2024 — McMap. All rights reserved.