apache / apache/maven-surefire
[SUREFIRE-2296] Classpath-Resource is not correctly resolved
- Dominant language
- Java
- Stars
- 461
- Forks
- 588
- Avg merge
- 1d 8h
- Merged PRs (30d)
- 19
Description
**[Pascal Knüppel](https://issues.apache.org/jira/secure/ViewProfile.jspa?name=captgoldfish)** opened **[SUREFIRE-2296](https://issues.apache.org/jira/browse/SUREFIRE-2296?redirect=false)** and commented
We got a multi-module project (no jigsaw), and we have a module named "constants". We are using this module as dependency in all other sub-modules.
the "constants"-module holds some css-files that we are sharing across two UI modules. And now we wrote unit-tests that prove, that we can serve these resources without authentication by calling the appropriate URL (springboot test).
This does not work if the tests are executed with maven. It works from the IDE and I will shortly show some code parts, and explain what is happening:
1. We start with reading all available css and javascript files that should be accessible. We have standard URL paths for these so we read them dynamically in the unit tests so that the unit tests will adjust themselves:
```java
public static Stream getAllLoadableResources()
{
List resourceUrls = new ArrayList<>();
BiConsumer addFileUrls = (path, resourceType) -> {
final String resourcesPath = path + "/" + resourceType;
URL url = ThymeleafConfigTest.class.getResource(resourcesPath);
log.warn("\nresourcePath: {}\nurl.path(): {}", resourceType, url == null ? null : url.getPath());
Optional.ofNullable(url).ifPresent(resourceUrl -> {
File resourceDirectory = new File(resourceUrl.getPath());
for ( File resourceFile : Objects.requireNonNull(resourceDirectory.listFiles()) )
{
resourceUrls.add("/" + resourceType + "/" + resourceFile.getName());
}
});
};
final String testResourcesClasspath = "/de/governikus/autent/consent/ui/custom/resources";
addFileUrls.accept(DefaultPaths.COMMON_RESOURCES_PATH, "css");
addFileUrls.accept(ConsentUi.BASE_PATH + "/resources", "css");
addFileUrls.accept(testResourcesClasspath, "css");
addFileUrls.accept(DefaultPaths.COMMON_RESOURCES_PATH, "js");
addFileUrls.accept(ConsentUi.BASE_PATH + "/resources", "js");
addFileUrls.accept(testResourcesClasspath, "js");
addFileUrls.accept(DefaultPaths.COMMON_RESOURCES_PATH, "images");
addFileUrls.accept(ConsentUi.BASE_PATH + "/resources", "images");
addFileUrls.accept(testResourcesClasspath, "images");
MatcherAssert.assertThat(resourceUrls,
Matchers.containsInAnyOrder(Matchers.equalTo("/css/bootstrap.min.css"),
...);
return resourceUrls.stream().map(Arguments::arguments);
}
/**
* verifies that the expected javascript, images and css files are loadable
*/
@ParameterizedTest
@MethodSource("getAllLoadableResources")
void testResourceHandler(String location)
{
HttpResponse response = getUnirestClient().get(location).asString();
Assertions.assertEquals(HttpStatus.OK, response.getStatus());
}
```
The problematic line is this one:
```java
ThymeleafConfigTest.class.getResource(resourcesPath);
```
**Why?**
The test is part of our module "consent-ui" and it tries to access resources of the module "constants"
* If we execute the test within the IDE, the resources are read from the target-directory created when built.
* If we execute the test with the maven-surefire-plugin, we get a problem because it tries to read the resources from the jar-file within the ".m2/repository"-directory.
_jar:file:/C:/Users/${user-name}/.m2/repository/de/.../constants/3.1.2-SNAPSHOT/constants-3.1.2-SNAPSHOT.jar!/de/.../constants/resources/css_
I am of course not able to retrieve the files from there.
_We have added the base-jar and the test-jar of this module to our module:_
```java
de.governikus.autent.crucis
constants
de.governikus.autent.crucis
constants
test-jar
test
```
{_}{_}I am wondering why I am not able to let the path resolve to "${project.parent.basedir}/constants/src/main/resources/...". To achieve that I tried the following:
```java
org.apache.maven.plugins
maven-surefire-plugin
!integration-test
${project.parent}/constants/target/classes
${project.parent}/constants/target/classes/*
${project.parent}/constants/target/classes/**
${project.parent.basedir}/constants/target/classes
${project.parent.basedir}/constants/target/classes/*
${project.parent.basedir}/constants/target/classes/**
${absolute-path-to-project}/constants/target/classes
${absolute-path-to-project}\constants
${absolute-path-to-project}/constants/target/classes/*
${absolute-path-to-project}/constants/target/classes/**
false
```
I tried as many variations as I could to check if it makes a difference
But this does not seem to have any effect.
If I look at the system-properties, I see this:
```java
surefire.test.class.path ->
${absolute-path-to-project}\consent-ui\target\test-classes;
${absolute-path-to-project}\consent-ui\target\classes;
C:\Users\${user-name}\.m2\repository\de\${class-path}\constants\3.1.2-SNAPSHOT\constants-3.1.2-SNAPSHOT.jar;
C:\Users\${user-name}\.m2\repository\org\springframework\boot\spring-boot-starter-web\3.4.4\spring-boot-starter-web-3.4.4.jar;
C:\Users\${user-name}\.m2\repository\org\springframework\boot\spring-boot-starter\3.4.4\spring-boot-starter-3.4.4.jar;
C:\Users\${user-name}\.m2\repository\org\springframework\boot\spring-boot\3.4.4\spring-boot-3.4.4.jar;
C:\Users\${user-name}\.m2\repository\org\springframework\boot\spring-boot-autoconfigure\3.4.4\spring-boot-autoconfigure-3.4.4.jar;
C:\Users\${user-name}\.m2\repository\org\springframework\boot\spring-boot-starter-logging\3.4.4\spring-boot-starter-logging-3.4.4.jar;
C:\Users\${user-name}\.m2\repository\org\yaml\snakeyaml\2.3\snakeyaml-2.3.jar;
C:\Users\${user-name}\.m2\repository\org\springframework\boot\spring-boot-starter-json\3.4.4\spring-boot-starter-json-3.4.4.jar;
C:\Users\${user-name}\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\
```
Is there any way, to adjust the classpath in a way, that I can make surefire read the resources from the target-directory of the sibling-module?
---
No further details from [SUREFIRE-2296](https://issues.apache.org/jira/browse/SUREFIRE-2296?redirect=false)
Contributor guide
Research direction
Start by examining the maven-surefire-plugin configuration around additionalClasspathElements and useSystemClassLoader, then reproduce the reported difference between IDE execution and Maven execution with the multi-module setup described. Done means the sibling module's resources are resolved from the intended target/classes location during Surefire tests, rather than only from the dependency JAR.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- build-system, testing
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 28/100