Skip to content
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

QuarkusIntegrationTest fails with ClassCastException #20552

Closed
denis-anisimov opened this issue Oct 6, 2021 · 15 comments
Closed

QuarkusIntegrationTest fails with ClassCastException #20552

denis-anisimov opened this issue Oct 6, 2021 · 15 comments
Labels
area/testing kind/bug Something isn't working triage/invalid This doesn't seem right

Comments

@denis-anisimov
Copy link

Describe the bug

@QuarkusIntegrationTest may fail with the following exception

java.lang.RuntimeException: java.lang.ClassCastException: class io.quarkus.test.junit.RunningAppConfigResolver$1 cannot be cast to class io.smallrye.config.SmallRyeConfig (io.quarkus.test.junit.RunningAppConfigResolver$1 and io.smallrye.config.SmallRyeConfig are in unnamed module of loader 'app')
Caused by: java.lang.ClassCastException: class io.quarkus.test.junit.RunningAppConfigResolver$1 cannot be cast to class io.smallrye.config.SmallRyeConfig (io.quarkus.test.junit.RunningAppConfigResolver$1 and io.smallrye.config.SmallRyeConfig are in unnamed module of loader 'app')

Expected behavior

No exception, test just work.

Actual behavior

The exception is thrown, test is failing.

How to Reproduce?

IT test annotated with @QuarkusTest works without any problems but it executes everything in the same JVM.
Once it changed to @QuarkusIntegrationTest sometimes it may throw this exception.
Sometimes the test refuses to start Quarkus because the port is occupied (may be it has not been shutdown properly after the previous run ?)

Output of uname -a or ver

Linux, version 4.14.225-169.362.amzn2.x86_64

Output of java -version

Java 8

GraalVM version (if different from Java)

No response

Quarkus version or git rev

2.3.0.Final

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

No response

Additional information

Upgraded Quarkus version to 2.3.0 where this fix is done : #20049

Now the tests are executed somehow but some tests are failing.

@denis-anisimov denis-anisimov added the kind/bug Something isn't working label Oct 6, 2021
@quarkus-bot
Copy link

quarkus-bot bot commented Oct 6, 2021

/cc @geoand

@geoand
Copy link
Contributor

geoand commented Oct 6, 2021

Thanks for reporting.

Can you attach a sample project that exhibits this behavior? Asking because I have personally never seen this...

@geoand geoand added the triage/needs-reproducer We are waiting for a reproducer. label Oct 6, 2021
@denis-anisimov
Copy link
Author

yeah, I understand.

I think I know the reason....
I forgot to change QuarkusTest in one of our ITs to @QuarkusIntegrationTest (in fact I didn't, it's just merge conflict consequence).
So almost all the tests are executed as QuarkusIntegrationTest but one is executed as a QuarkusTest.
As a result for one test the new JVM is not started but it's executed in the same but for other tests new JVM is started and they are executed there.
And that introduce a collision apparently: some class is trying to be used being loaded by another classloader (and most likely it should be used just by another JVM).
That explains the error and the reason why sometimes the server port is already occupied : it's occupied by another JVM.

I still think this is a bug : it's either should be possible to run both QuarkusTest and QuarkusIntegrationTest in the same module via maven surefire plugin or at least there should be a clean indication what's going wrong.

@geoand
Copy link
Contributor

geoand commented Oct 6, 2021

I still think this is a bug : it's either should be possible to run both QuarkusTest and QuarkusIntegrationTest in the same module via maven surefire plugin or at least there should be a clean indication what's going wrong.

This is not possible because @QuarkusIntegrationTest needs access to the built Quarkus application, thus these tests need to be run by maven failsafe (or to be more precise, it needs to be run in the verify phase).

@geoand geoand closed this as completed Oct 6, 2021
@geoand geoand added triage/invalid This doesn't seem right and removed triage/needs-reproducer We are waiting for a reproducer. labels Oct 6, 2021
@denis-anisimov
Copy link
Author

Sorry, I don't have the localized simple project for this.
It happened here https://github.com/vaadin/quarkus within the ITs: https://github.com/vaadin/quarkus/tree/master/integration-tests/development
this commit should fix the problem : vaadin/quarkus@74ef495
but this PR without this commit is failing : vaadin/quarkus#39

@denis-anisimov
Copy link
Author

denis-anisimov commented Oct 6, 2021

This is apparently possible because once I replaced QuarkusTest to QuarkusIntegrationTest in one of the tests the build passed.

Yes, I agree that surefire plugin should not be used to run ITs. So the config is kind of incorrect.
But it's definitely possible to run QuarkusIntegrationTest using surefire plugin and it's possible to run QuarkusTest using surefire plugin.
If you have both of them then the exception reported in the ticket will be thrown (or the port will be occupied).
So I may be make it's impossible explicitly : since now it's possible.

Whatever, I identified a problem , it's up to you to decide what to do with this. I'm fine if it's closed since the configuration is initially wrong.

@geoand
Copy link
Contributor

geoand commented Oct 6, 2021

We can certainly try to improve the error message to help users in the futrue.

Thanks for the information!

@westarne
Copy link

westarne commented Dec 7, 2021

Hello,

since this is exactly what we experienced now, I wanted to make some additions, so I hope it's ok to comment on the closed issue. Otherwise I could also open another issue, linking to this one.

First of all we would like to run @QuarkusIntegrationTest against the native image as well as @QuarkusTest in the mvn verify step using the failsafe plugin. We will be doing some smoke tests against the deployed service in the @QuarkusTest for general availability and connectivity checks, as well as other tests that should not block the build/deployment. In the @QuarkusIntegrationTest we want to test more complex scenarios with mocked backend APIs to get a good coverage on the compiled native application.
We cannot move the smoke tests to the other test steps as it's not deployed before packaging obviously. So we'd need to actually run all the tests on the native image (no actual smoke tests) or run a @QuarkusIntegrationTest just for some RestAssured queries. For us it would definitely be great to be able to include the smoke testing there and not having to use a different framework.

We tested this using Quarkus 2.5.0.Final and 2.5.1.Final. The error occurs exactly at ~/.m2/repository/io/quarkus/quarkus-core/2.5.1.Final/quarkus-core-2.5.1.Final-sources.jar!/io/quarkus/runtime/configuration/ConfigInstantiator.java:56:

final SmallRyeConfig config = (SmallRyeConfig) ConfigProvider.getConfig();

I was wondering, why it is necessary there to cast it to SmallRyeConfig? In the below code I did not see any reference where this specific class would be required. The problem seems to be that running a @QuarkusIntegrationTest first, the ConfigProvier.getConfig() will actually return a SmallRyeConfig, but otherwise (run a @QuarkusTest first and then a @QuarkusIntegrationTest it will return a RunningAppConfigResolver which cannot be casted.

With the previous version 2.2.1.Final we used, mixing these tests was still possible, so as mentioned this seems to have been introduced with 2.3.0.Final. And it worked well for us before. Was there a specific problem with that previous behaviour that was fixed? Wouldn't it be possible to simply remove the SmallRyeConfig config cast?

Thanks and best regards.

@geoand
Copy link
Contributor

geoand commented Dec 7, 2021

so I hope it's ok to comment on the closed issue.

it most certainly is :)

as well as @QuarkusTest in the mvn verify step using the failsafe plugin

This is not possible.

The error occurs exactly at ~/.m2/repository/io/quarkus/quarkus-core/2.5.1.Final/quarkus-core-2.5.1.Final-sources.jar!/io/quarkus/runtime/configuration/ConfigInstantiator.java:56

What is the complete stacktrace?

@westarne
Copy link

westarne commented Dec 7, 2021

Thanks first of all for the quick answer!

as well as @QuarkusTest in the mvn verify step using the failsafe plugin

This is not possible.

It did work prior to 2.3.0.Final though. Was that a missing restriction in there? So It's not intended to run anything other than @QuarkusIntegrationTest in the failsafe mvn verify in general or is that some restriction that could be changed?

What is the complete stacktrace?

The full stack trace (as visible in IntelliJ) is:

java.lang.RuntimeException: java.lang.ClassCastException: class io.quarkus.test.junit.RunningAppConfigResolver$1 cannot be cast to class io.smallrye.config.SmallRyeConfig (io.quarkus.test.junit.RunningAppConfigResolver$1 and io.smallrye.config.SmallRyeConfig are in unnamed module of loader 'app')

	at io.quarkus.test.junit.QuarkusIntegrationTestExtension.throwBootFailureException(QuarkusIntegrationTestExtension.java:265)
	at io.quarkus.test.junit.QuarkusIntegrationTestExtension.beforeEach(QuarkusIntegrationTestExtension.java:70)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeBeforeEachCallbacks$2(TestMethodTestDescriptor.java:163)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeBeforeMethodsOrCallbacksUntilExceptionOccurs$6(TestMethodTestDescriptor.java:199)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeBeforeMethodsOrCallbacksUntilExceptionOccurs(TestMethodTestDescriptor.java:199)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeBeforeEachCallbacks(TestMethodTestDescriptor.java:162)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:129)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
	at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
	at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
	at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: java.lang.ClassCastException: class io.quarkus.test.junit.RunningAppConfigResolver$1 cannot be cast to class io.smallrye.config.SmallRyeConfig (io.quarkus.test.junit.RunningAppConfigResolver$1 and io.smallrye.config.SmallRyeConfig are in unnamed module of loader 'app')
	at io.quarkus.runtime.configuration.ConfigInstantiator.handleObject(ConfigInstantiator.java:56)
	at io.quarkus.runtime.logging.LoggingSetupRecorder.handleFailedStart(LoggingSetupRecorder.java:71)
	at io.quarkus.runtime.logging.LoggingSetupRecorder.handleFailedStart(LoggingSetupRecorder.java:66)
	at io.quarkus.test.junit.IntegrationTestUtil.activateLogging(IntegrationTestUtil.java:313)
	at io.quarkus.test.junit.QuarkusIntegrationTestExtension.doProcessStart(QuarkusIntegrationTestExtension.java:197)
	at io.quarkus.test.junit.QuarkusIntegrationTestExtension.ensureStarted(QuarkusIntegrationTestExtension.java:107)
	at io.quarkus.test.junit.QuarkusIntegrationTestExtension.beforeAll(QuarkusIntegrationTestExtension.java:79)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeBeforeAllCallbacks$10(ClassBasedTestDescriptor.java:381)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeBeforeAllCallbacks(ClassBasedTestDescriptor.java:381)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:205)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:80)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:148)
	... 33 more

I can set up an example project later as well, if wanted. In general it's easy to trigger this e.g. from IntelliJ or maven, you just have to make sure that a @QuarkusTest is executed first and the @QuarkusIntegrationTest second (in our case with settings same as @NativeImageTest)

@geoand
Copy link
Contributor

geoand commented Dec 7, 2021

It did work prior to 2.3.0.Final though. Was that a missing restriction in there? So It's not intended to run anything other than @QuarkusIntegrationTest in the failsafe mvn verify in general or is that some restriction that could be changed?

If it worked, it worked by chance.

So It's not intended to run anything other than @QuarkusIntegrationTest in the failsafe mvn verify in general

Correct

@dxps
Copy link
Contributor

dxps commented Jan 9, 2022

Can we please have some sort of summary ❓

I'm asking since I'm following Kubernetes Native Microservices with Quarkus and MicroProfile book, and eventually I got into this issue as well (after overcoming another one when NativeImageTest instead of QuarkusIntegrationTest annotation was used).

Just using mvn verify -Pnative in this sample simple example that used the currently latest Quarkus 2.6.1.Final.

If maven-failsafe-plugin is used on pom.xml line 99, then all the tests are skipped and the native image is built.

If maven-surefire-plugin is used on pom.xml line 99, then the tests are triggered, and the native related ones are failing:

[INFO] --- maven-surefire-plugin:3.0.0-M5:test (default-test) @ account_svc ---
[INFO] 
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running io.dxps.knqb.AccountResourceTest
2022-01-09 14:17:37,214 INFO  [io.quarkus] (main) Quarkus 2.6.1.Final on JVM started in 1.197s. Listening on: http://localhost:8081
2022-01-09 14:17:37,234 INFO  [io.quarkus] (main) Profile test activated. 
2022-01-09 14:17:37,235 INFO  [io.quarkus] (main) Installed features: [cdi, kubernetes, resteasy, resteasy-jsonb, smallrye-context-propagation, vertx]
[INFO] Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.425 s - in io.dxps.knqb.AccountResourceTest
[INFO] Running io.dxps.knqb.NativeAccountResourceTest
[ERROR] Tests run: 5, Failures: 0, Errors: 1, Skipped: 4, Time elapsed: 0.367 s <<< FAILURE! - in io.dxps.knqb.NativeAccountResourceTest
[ERROR] io.dxps.knqb.NativeAccountResourceTest.testRetrieveAll  Time elapsed: 0 s  <<< ERROR!
java.lang.RuntimeException: java.lang.ClassCastException: class io.quarkus.test.junit.RunningAppConfigResolver$1 cannot be cast to class io.smallrye.config.SmallRyeConfig (io.quarkus.test.junit.RunningAppConfigResolver$1 and io.smallrye.config.SmallRyeConfig are in unnamed module of loader 'app')
Caused by: java.lang.ClassCastException: class io.quarkus.test.junit.RunningAppConfigResolver$1 cannot be cast to class io.smallrye.config.SmallRyeConfig (io.quarkus.test.junit.RunningAppConfigResolver$1 and io.smallrye.config.SmallRyeConfig are in unnamed module of loader 'app')

Which is abnormal anyway, as the native tests should run against the built image and not triggered before building it.

Any feedback is appreciated. Thanks!

@geoand
Copy link
Contributor

geoand commented Jan 9, 2022

NativeAccountResourceTest should be renamed to NativeAccountResourceIT

@dxps
Copy link
Contributor

dxps commented Jan 9, 2022

Unbelievable! 🎉 It works! Really appreciated the quick feedback! @geoand 🙏

This naming convention should be clearly emphasized in the docs and guides.
Lookink into existing Getting started testing guide, I cannot see this convention stated.
I'll still search for it and otherwise come back with a small PR to help in this regard.

@geoand
Copy link
Contributor

geoand commented Jan 9, 2022

Unbelievable! tada It works! Really appreciated the quick feedback! @geoand pray

You are welcome!

This naming convention should be clearly emphasized in the docs and guides. Lookink into existing Getting started testing guide, I cannot see this convention stated. I'll still search for it and otherwise come back with a small PR to help in this regard.

It is mentioned in https://quarkus.io/guides/building-native-image, but feel free to open a PR if you feel there is an improvement to be made.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/testing kind/bug Something isn't working triage/invalid This doesn't seem right
Projects
None yet
Development

No branches or pull requests

4 participants