Repository navigation
The new support for testcontainers in Spring Boot 3.1.0 does not work with native tests #35663
Copy link
Copy link
Closed
Description
I have created a Github repo that can be used to reproduce the error: https://github.com/magnus-larsson/sb31-nativetest-demo.
The sample code contains a test that uses the new support for testcontainers together with Postgresql.
Running tests that use testcontainers for Postgresql works fine:
./gradlew clean test
Building a jar file and a native image and running them with a Postregsql db in Docker also works fine:
docker-compose up -d
export SPRING_DATASOURCE_URL=jdbc:postgresql://localhost/bp
export SPRING_DATASOURCE_USERNAME=bp
export SPRING_DATASOURCE_PASSWORD=bp
./gradlew build
java -jar build/libs/tcdemo-0.0.1-SNAPSHOT.jar
curl localhost:8080/customers
CTRL/C
./gradlew nativeBuild
java -jar build/libs/tcdemo-0.0.1-SNAPSHOT.jar
curl localhost:8080/customers
CTRL/C
docker-compose down
But, when running native tests, they fail:
./gradlew clean nativeTest
Error message:
Failures (1):
JUnit Jupiter:TcdemoApplicationTests
ClassSource [className = 'com.example.tcdemo.TcdemoApplicationTests', filePosition = null]
=> java.lang.ExceptionInInitializerError
org.springframework.test.context.TestContextManager.<init>(TestContextManager.java:113)
org.junit.jupiter.engine.execution.ExtensionValuesStore.lambda$getOrComputeIfAbsent$4(ExtensionValuesStore.java:86)
org.junit.jupiter.engine.execution.ExtensionValuesStore$MemoizingSupplier.computeValue(ExtensionValuesStore.java:223)
org.junit.jupiter.engine.execution.ExtensionValuesStore$MemoizingSupplier.get(ExtensionValuesStore.java:211)
org.junit.jupiter.engine.execution.ExtensionValuesStore$StoredValue.evaluate(ExtensionValuesStore.java:191)
[...]
Suppressed: java.lang.NoClassDefFoundError: Could not initialize class org.springframework.test.context.BootstrapUtils
org.springframework.test.context.TestContextManager.<init>(TestContextManager.java:113)
org.junit.jupiter.engine.execution.ExtensionValuesStore.lambda$getOrComputeIfAbsent$4(ExtensionValuesStore.java:86)
org.junit.jupiter.engine.execution.ExtensionValuesStore$MemoizingSupplier.computeValue(ExtensionValuesStore.java:223)
org.junit.jupiter.engine.execution.ExtensionValuesStore$MemoizingSupplier.get(ExtensionValuesStore.java:211)
org.junit.jupiter.engine.execution.ExtensionValuesStore$StoredValue.evaluate(ExtensionValuesStore.java:191)
[...]
Caused by: java.lang.IllegalStateException: Failed to load class for @org.springframework.test.context.web.WebAppConfiguration
org.springframework.test.context.BootstrapUtils.loadWebAppConfigurationClass(BootstrapUtils.java:213)
org.springframework.test.context.BootstrapUtils.<clinit>(BootstrapUtils.java:63)
[...]
Caused by: java.lang.ClassNotFoundException: org.springframework.test.context.web.WebAppConfiguration
[email protected]/java.lang.Class.forName(DynamicHub.java:1132)
org.springframework.util.ClassUtils.forName(ClassUtils.java:284)
org.springframework.test.context.BootstrapUtils.loadWebAppConfigurationClass(BootstrapUtils.java:209)
[...]
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
type: bugA general bugA general bug
Activity
1713612859 commentedon May 28, 2023
please check yml.properties
wilkinsona commentedon May 30, 2023
AOT processing of
TcdemoApplicationTestsfails:This leads to incomplete runtime hints and the subsequent
ClassNotFoundException: org.springframework.test.context.web.WebAppConfiguration.@sbrannen I wonder if AOT processing of tests should fail fast in this situation? If AOT processing has failed, running the tests is very unlikely to succeed and it's easy to miss the earlier error, particularly when the subsequent failure is apparently unrelated.
wilkinsona commentedon May 30, 2023
With a local change in place to work around the AOT processing failure, Testcontainers itself does not work with native tests. They fail when trying to bind
~/.docker/config.jsoninto aDockerConfigFileinstance:There is reachability metadata for it but it appears to be incomplete. The metadata is for Testcontainers 1.17.6 and the above failure occurs with 1.18.0 so the problem may be have been introduced in Testcontainers 1.18 or the tests for the reachability metadata may not drive this code path.
With the AOT processing workaround in place,
nativeTestsucceeds with the following additional reflection config:{ "name": "org.testcontainers.shaded.com.github.dockerjava.core.DockerConfigFile", "allDeclaredMethods": true, "allDeclaredConstructors": true }wilkinsona commentedon May 30, 2023
I've opened oracle/graalvm-reachability-metadata#301 to update the reachability metadata so that
~/.docker/config.jsoncan be deserialised into aDockerConfigFileinstance.magnus-larsson commentedon Jun 2, 2023
Hello @wilkinsona, and thanks for your support! I noticed that your PR to the reachability project has been approved and merged, great!
How can I test if your PR helps with the problem reported in this issue?
wilkinsona commentedon Jun 2, 2023
You can't I'm afraid. We need to make a change in Boot before you'll reach the point where the Testcontainers problem occurs.
magnus-larsson commentedon Jun 2, 2023
Ok, thanks for the update!
Any tentative ideas for what Spring Boot version will get the change implemented?
magnus-larsson commentedon Jun 7, 2023
Hello @wilkinsona, and thanks for the bug fix!
I tried it out using Spring Boot 3.1.1-SNAPSHOT.
Now I get the error message you referred to above:
Will oracle/graalvm-reachability-metadata#301 resolve this or what needs to be done before the
./gradlew clean nativeTestworks with my sample code?wilkinsona commentedon Jun 7, 2023
Yes, oracle/graalvm-reachability-metadata#301 should resolve this. Until the reachability metadata is released, you could provide similar hints yourself:
This registrar can then be imported by your test class:
Fix `@ServiceConnection` in native tests