Skip to content

[Test][ClassLoader] Quarkus 3.22 throws when tests run with junit-platform.properties resource file #47646

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

Open
lloydmeta opened this issue May 1, 2025 · 8 comments
Assignees
Labels

Comments

@lloydmeta
Copy link

lloydmeta commented May 1, 2025

Describe the bug

Might be related to https://quarkus.io/blog/test-classloading-rewrite/

If you create a junit-platform.properties file in src/test/resources and run ./gradlew test it throws

java.lang.RuntimeException: Internal error. The test class class com.beachape.GreetingResourceTest should have been loaded with a QuarkusClassLoader, but instead it was loaded with jdk.internal.loader.ClassLoaders$AppClassLoader@2626b418. This is caused by the FacadeClassLoader not correctly identifying this class as a QuarkusTest.

Prior to 3.22, this wouldn't throw.

Expected behavior

It should run.

Actual behavior

It throws

java.lang.RuntimeException: Internal error. The test class class com.beachape.GreetingResourceTest should have been loaded with a QuarkusClassLoader, but instead it was loaded with jdk.internal.loader.ClassLoaders$AppClassLoader@2626b418. This is caused by the FacadeClassLoader not correctly identifying this class as a QuarkusTest.
	at io.quarkus.test.junit.QuarkusTestExtension.getClassLoaderFromTestClass(QuarkusTestExtension.java:337)
	at io.quarkus.test.junit.QuarkusTestExtension.ensureStarted(QuarkusTestExtension.java:631)
	at io.quarkus.test.junit.QuarkusTestExtension.beforeAll(QuarkusTestExtension.java:712)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1597)

How to Reproduce?

https://github.com/lloydmeta/quarkus-3.22-test-bug-repo

Output of uname -a or ver

24.4.0 Darwin Kernel Version 24.4.0: Fri Apr 11 18:28:23 PDT 2025; root:xnu-11417.101.15~117/RELEASE_X86_64 x86_64

Output of java -version

java 23.0.2 2025-01-21

Quarkus version or git rev

3.22.1

Build tool (ie. output of mvnw --version or gradlew --version)

Gradle 8.13

Additional information

❯ ./gradlew test --no-build-cache
Discovered 2 'junit-platform.properties' configuration files on the classpath (see below); only the first (*) will be used.
- file:/Users/lloyd/Documents/djava/quarkus-test-bug-repo/build/resources/test/junit-platform.properties (*)
- jar:file:/Users/lloyd/.gradle/caches/modules-2/files-2.1/io.quarkus/quarkus-junit5-config/3.21.4/1754ab3d86388a2957df43f208fbc8f9417c47eb/quarkus-junit5-config-3.21.4.jar!/junit-platform.properties
Discovered 2 'junit-platform.properties' configuration files on the classpath (see below); only the first (*) will be used.
- file:/Users/lloyd/Documents/djava/quarkus-test-bug-repo/build/resources/test/junit-platform.properties (*)
- jar:file:/Users/lloyd/.gradle/caches/modules-2/files-2.1/io.quarkus/quarkus-junit5-config/3.21.4/1754ab3d86388a2957df43f208fbc8f9417c47eb/quarkus-junit5-config-3.21.4.jar!/junit-platform.properties

[Incubating] Problems report is available at: file:///Users/lloyd/Documents/djava/quarkus-test-bug-repo/build/reports/problems/problems-report.html

Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

For more on this, please refer to https://docs.gradle.org/8.13/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.

BUILD SUCCESSFUL in 31s
11 actionable tasks: 11 executed
❯ ./gradlew test --no-build-cache
Discovered 2 'junit-platform.properties' configuration files on the classpath (see below); only the first (*) will be used.
- file:/Users/lloyd/Documents/djava/quarkus-test-bug-repo/build/resources/test/junit-platform.properties (*)
- jar:file:/Users/lloyd/.gradle/caches/modules-2/files-2.1/io.quarkus/quarkus-junit5-config/3.22.1/d44e0e34a555e8291c2d8af1cef830283d387b85/quarkus-junit5-config-3.22.1.jar!/junit-platform.properties
Discovered 2 'junit-platform.properties' configuration files on the classpath (see below); only the first (*) will be used.
- file:/Users/lloyd/Documents/djava/quarkus-test-bug-repo/build/resources/test/junit-platform.properties (*)
- jar:file:/Users/lloyd/.gradle/caches/modules-2/files-2.1/io.quarkus/quarkus-junit5-config/3.22.1/d44e0e34a555e8291c2d8af1cef830283d387b85/quarkus-junit5-config-3.22.1.jar!/junit-platform.properties

> Task :test FAILED

GreetingResourceTest > initializationError FAILED
    java.lang.RuntimeException at QuarkusTestExtension.java:337

1 test completed, 1 failed

[Incubating] Problems report is available at: file:///Users/lloyd/Documents/djava/quarkus-test-bug-repo/build/reports/problems/problems-report.html

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':test'.
> There were failing tests. See the report at: file:///Users/lloyd/Documents/djava/quarkus-test-bug-repo/build/reports/tests/test/index.html

* Try:
> Run with --scan to get full insights.

Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

For more on this, please refer to https://docs.gradle.org/8.13/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.

BUILD FAILED in 5s
11 actionable tasks: 9 executed, 2 up-to-date

Workarounds

  • Going back to 3.21.4 works
  • Removing the properties file works
@lloydmeta lloydmeta added the kind/bug Something isn't working label May 1, 2025
@kevinross
Copy link

I wonder if my own issue is related? If you have a package-private constructor or method in one (gradle) subproject (call it "A") and try to use it in another subproject (call it "tests") via extending the class (yes, split-package is discouraged, and this is probably why, but I digress), the class in "tests" is loaded in a different classloader than the parent class in "A", causing an IllegalAccessError:

project_common/src/main/java/com/example/ExampleInterface.java:

public interface ExampleInterface {
    List<String> performSomeAlgorithm(POJO object, int count);
}

project_A/src/main/java/com/example/ProductionImplementationClass.java:

public class ProductionImplementationClass implements ExampleInterface {
    public ProductionImplementationClass(String param) {
        // impl elided
    }
    @VisibleForTesting
    ProductionImplementationClass() {
        // impl elided
    }
    @VisibleForTesting
    List<String> performSomeAlgorithm(POJO object, int count) {
        // impl elided
    }
}

tests/src/main/java/com/example/TestProductionImplementationClass.java:

public class TestProductionImplementationClass extends ProductionImplementationClass {
    List<String> testPerformSomeAlgorithm(POJO object, int count) {
        return performSomeAlgorithm(object, count);
    }
}

This compiles perfectly fine, but when it's executed we find that ProductionImplementationClass is loaded in a different classloader than TestProductionImplementationClass so cannot invoke the constructor (either implicitly or explicitly) nor the method under test. Note that the test class is in the main source set: this is intentional.

For context: in our service, project_common is a subproject that contains code common to all applications contained in the root project, project_A is one self-contained application, and tests is our test framework and tests. project_A depends on project_common via a gradle implementation dependency, and tests depends on both also via a gradle implementation dependency declaration.

This exact arrangement functions as-is in 3.21.4 but breaks on upgrade to 3.22.1. I'm not opposed to changing the visibility of the methods/ctors in question, but I wonder what exact change may have led to this and whether it could be a bug or intended behaviour. And, yes, split-packages are discouraged, and I should probably make the change if only for that reason alone, but again... same question: bug or intentional.

@gsmet
Copy link
Member

gsmet commented May 1, 2025

@kevinross could you maybe create a separate issue with a reproducer? I'm not sure both are related and it's probably better to track them separately.

Copy link

quarkus-bot bot commented May 1, 2025

/cc @geoand (testing)

@gsmet
Copy link
Member

gsmet commented May 1, 2025

/cc @holly-cummins

@holly-cummins holly-cummins self-assigned this May 1, 2025
@holly-cummins
Copy link
Contributor

Ah yes, this is definitely related to my changes. There may be a workaround, I'll have a look.

@kevinross
Copy link

Should I create a new ticket then...? I commented on this one due to the clear connection to classloaders in the stacktrace - but I'm happy to create a new one and attach a proper reproducer.

@holly-cummins
Copy link
Contributor

Yes please, @kevinross. The root cause is most likely the same (#34681), but I suspect the fix for your issue will be very different. The changes in 3.22 are intended to avoid the sort of "tests in wrong classloader" problem you're seeing but obviously didn't have the intended effect for your scenario.

@kevinross
Copy link

@holly-cummins here you go!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Development

No branches or pull requests

4 participants