Spring Boot 4.0.0-M3 Spring Framework 7.0.0-M9
I'm not sure if this is an issue with Boot or Framework (or both).
As of Framework 7, the Spring Test Context Framework will suspend cached application contexts when they're no longer being used by tests, and restarted when the next test uses them again. It appears that some beans don't fully support this, at least the embedded web server and the reactor resource factory. When multiple test classes share the same context (due to identical context configurations), after the first test is done, the embedded server and the reactor resource factory are shut down, butwhen the next test retrieves the context from the cache, they're not started again.
This reproducer demonstrates this: demo5.zip
It has three groups of test classes with two tests each, sharing a context between them.
Two test groups use WebTestClient
to call the embedded server (on the defined or on a random port). The second test in each group fails each time because the server is not running.
The third test group uses WebClient
to call the embedded server. The second test in the group fails due to the event loop being shut down and not accepting tasks.
Note that each test succeeds when executed individually, but tests start to fail when we start all tests at once.
Comment From: wilkinsona
Thanks for the report and sample. The problem's caused by the ReactorResourceFactory
participating in the pause and resume of the context. When it is paused it calls stop()
that calls reactor.netty.resources.LoopResources.disposeLater(Duration, Duration)
. When resumed, start()
is called but this creates an entirely new LoopResources
instance. Any component that had previously called ReactorResourceFactory.getLoopResources()
is left referencing the old, disposed LoopResources
and is broken.
I think the fix will be for ReactorResourceFactory
to implement isPausable()
and return false
but that will be up to the Framework team to decide. We'll transfer this issue to them for further consideration.
Comment From: sbrannen
@kzander91, thanks for reporting this, and @wilkinsona, thanks for the analysis. 👍
I did the following:
- Overrode
isPauseable()
to returnfalse
inReactorResourceFactory
- Built Framework locally (test suite passes)
- Published to Maven local
- Updated
pom.xml
in the demo project as follows
<properties>
<java.version>25</java.version>
<spring-framework.version>7.0.0-SNAPSHOT</spring-framework.version>
<junit-jupiter.version>6.0.0</junit-jupiter.version>
</properties>
And all tests in the demo project now pass.
Thus, making ReactorResourceFactory
not pauseable seems like a viable solution; however, I will check with the rest of the team before proceeding with that change.
Comment From: sbrannen
This has been addressed in d404fdafa00612dc74acf5a08ecc9284ec47dcd1 and will be available in upcoming 7.0.0-SNAPSHOT artifacts.
@kzander91, feel free to try out a snapshot and report back if you run into any issues.
Cheers,
Sam
Comment From: kzander91
@sbrannen thanks for the quick fix, no issues on my side 👍