-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tests not found via classpath scanning within nested JAR in Spring Boot JAR #1724
Comments
Thanks for raising the issue. I've tentatively slated this for 5.4 M2 for the purpose of team discussion. |
Today I stumbled over the same problems. Thanks for creating a demo project @ferstl! I'll a) push an integration test showing the issue is even applicable when test classes are jarred (not nested) and b) tackle the underlying missing feature/enhancement after 5.5 GA is released. |
Team Decision: Move to General Backlog to see whether this use case is relevant for other users as well. |
Yes, this problem is relevant for other users. Please fix it. |
If this issue is ever addressed, I wonder if it would be worth including ClassGraph, shadowing it, and using it instead of |
Interesting idea, @jbduncan! I didn't realize that ClassGraph had explicit support for Spring Boot's proprietary JAR structure until now.
|
I've spiked implementing The build is currently broken due to some error in our module compilation setup: @sormuras Let's take a look at that when you're back. |
Why so late? 🤓 Looks like the ClassGraph JAR is not available when compiling the modules. Neither on the module-path, nor on the class-path. Will look into it ... soon. |
Hello
I can see that the problem is in CloseablePath.create(baseUri) method where you split the path by "!" symbol. It returns "BOOT-INF/classes" instead of "BOOT-INF/classes/com.target.package.name" The reason is that full path in spring boot jar contains two "!" signs like this I decided to use -c and pass full class name and it works. But won't be handy if I have a lot of tests |
@epam-valerii is correct, the baseDir is incorrect so the subPackage variable in |
The team decision from above to wait for additional interest still stands. |
I've found a workaround. spring-projects/spring-boot#1828 (comment) With configuration below Spring Boot features work alongside with JUnit Console Launcher import com.github.jengelman.gradle.plugins.shadow.transformers.*
shadowJar {
zip64 true
manifest {
attributes 'Implementation-Title': 'Testing Jar File',
'Main-Class': 'org.junit.platform.console.ConsoleLauncher'
}
from sourceSets.test.output
configurations = [project.configurations.testRuntimeClasspath]
exclude '**/Log4j2Plugins.dat'
// Required for Spring
mergeServiceFiles()
append 'META-INF/spring.handlers'
append 'META-INF/spring.schemas'
append 'META-INF/spring.tooling'
transform(PropertiesFileTransformer) {
paths = ['META-INF/spring.factories' ]
mergeStrategy = "append"
}
} |
Same issue here, currently declaring every class via LauncherDiscoveryRequestBuilder |
Hit this issue for integration tests run using JUnit 5 that are packaged up for a CI/CD pipeline as a Spring Boot application. |
Just chiming in here. We ran into this issue as well. Our motivation for this is to run E2E-tests within a cluster by deploying a Spring Boot Application executing the tests using the JUnit5 platform launcher. |
Same issue here. Any update on this issue? |
No, but someone could pick up where I left off above: #1724 (comment) 🙂 |
hey there, also stumbled upon it. same issue: trying to package dependencies via the spring boot fat jar packager to run integration tests in a kubernetes cluster. I know, the problem does not exist when using other build plugins (e.g. maven shade plugin or assembly plugin). However, these plugins add quite a bit to the build time. The spring plugin is literally over 20x faster when assembling a fat jar. (that's because it does not extract and add all files to the target archive but just adds the archives itself) |
Looks like the following could be a workaround:
That way at least in our environment it seems to pick up all annotated test-classes. E.g.:
after that, we can use |
Yes. Please fix. I spent 2 days finding a solution to this problem of shadow jar not working with Spring Boot. BootJar not bringing in test classes, not getting any shadowjar to run the platform-console. I can confirm @valeratimofeev solution works. That will create a fat jar (make sure to run the compileTestJava first) that when executing -jar junit-platform-console-standalone-1.9.2.jar -cp yourshadow.jar -c your.test.Class it will execute. What a pain. |
Please note the Spring Boot 3.2.0 release notes:
Ignoring the typos in the example uri, this means that java's
Which happens because JUnit 5 assumes the jar uri is flat: junit5/junit-platform-commons/src/main/java/org/junit/platform/commons/util/CloseablePath.java Lines 54 to 61 in 8f5fbd0
While it in fact it is recursive private static final String JAR_URI_SEPARATOR = "!/";
String uriString = uri.toString();
int lastJarUriSeparator = uriString.lastIndexOf(JAR_URI_SEPARATOR);
String jarUri = uriString.substring(0, lastJarUriSeparator);
String jarEntry = uriString.substring(lastJarUriSeparator + 1); Worth noting that this will only work when scanning inside |
Jar uris follow the format[1]: ``` jar:<url>!/[<entry>] ``` So splitting should be done on the last `!/` rather than the first. Fixes: junit-team#1724 for Spring Boot 3.2 and later. 1. https://docs.oracle.com/javase/8/docs/api/java/net/JarURLConnection.html
Jar uris follow the format[1]: ``` jar:<url>!/[<entry>] ``` So splitting should be done on the last `!/` rather than the first. Fixes: junit-team#1724 for Spring Boot 3.2 and later. 1. https://docs.oracle.com/javase/8/docs/api/java/net/JarURLConnection.html
Jar uris follow the format[1]: ``` jar:<url>!/[<entry>] ``` So splitting should be done on the last `!/` rather than the first. Fixes: junit-team#1724 for Spring Boot 3.2 and later. 1. https://docs.oracle.com/javase/8/docs/api/java/net/JarURLConnection.html
With a relatively small change scanning the if (JAR_URI_SCHEME.equals(uri.getScheme())) {
String uriString = uri.toString();
if (uriString.startsWith("jar:file:") && uriString.contains("!/BOOT-INF/classes")) {
// Parsing jar:file:<file>!/BOOT-INF/classes!/[<entry>]
String[] parts = uri.toString().split("!");
String jarUri = parts[0];
String jarEntry = parts[1];
String subEntry = parts[2];
return createForJarFileSystem(new URI(jarUri), fileSystem -> fileSystem.getPath(jarEntry + subEntry), fileSystemProvider);
}
// Parsing: jar:<url>!/[<entry>]
int lastJarUriSeparator = uriString.lastIndexOf(JAR_URI_SEPARATOR);
String jarUri = uriString.substring(0, lastJarUriSeparator);
String jarEntry = uriString.substring(lastJarUriSeparator + 1);
return createForJarFileSystem(new URI(jarUri), fileSystem -> fileSystem.getPath(jarEntry), fileSystemProvider);
} |
Jar uris follow the format [1]: ``` jar:<url>!/[<entry>] ``` So splitting should be done on the last `!/` rather than the first. Fixes: #1724 for Spring Boot 3.2 and later. 1. https://docs.oracle.com/javase/8/docs/api/java/net/JarURLConnection.html
We are providing a test suite for our applications as Spring Boot application. The test suite is basically a set of regular JUnit 5 tests that are launched in the Spring Boot application.
The application is packaged as Spring Boot JAR (created with the
spring-boot-maven-plugin
).We do now have the problem, that the tests are not found when we are using
DiscoverySelectors.selectPackage()
and run the application as Spring Boot JAR. Everything works fine, when we select the tests by classname. Executing the application within an IDE works fine as well.The problem seems to be in
ClasspathScanner#findClassesForPath())
.Files.walkFileTree()
does not work with nested JAR files. A similar problem was already reported in #399.Steps to reproduce
I created a project on GitHub to reproduce this issue. When the
Application
is run within the IDE, everything works fine. When it is executed as Spring Boot JAR, the test is not found.Context
The text was updated successfully, but these errors were encountered: