I have a Spring Boot
+ WebFlux
application with the following structure:
- A controller
ControllerA
that uses a serviceServiceA
. ServiceA
uses aWebClient
to call a remote microservicemicroservice A
.- The URL of the endpoint in
microservice A
is configurable inapplication.yaml
.
Now I would like to test it using SpringBootTest
and JUnit 5 Jupiter
with the PER_CLASS
test lifecycle. For this, I want to mock the remote microservice using OkHttp MockWebServer
. The server is started before the first test method (@BeforeAll
) and stopped after all tests (@AfterAll
).
The problem is that the Spring container starts first, and then the test methods (and their before and after callbacks) are invoked. When the container starts it initializes the beans, and also ServiceA
with the URL of microservice A
from application.yaml
. Only afterwards is MockWebServer
started and I can query it for its URL, but at that point it's already too late and ServiceA
is already instantiated with the 'wrong' (real) URL.
I got it to work in various ways using various hacks (e.g. fixing the port by overriding the URL with @TestPropertySource
and then forcing WebTestServer
to use this port) but all have disadvantages (what if the port is takes by a parallel CI job?).
As we are only going to have more and more such integration tests in our codebase, we need a good solution for it. I am thinking of writing a custom TestExecutionListener
running before all of the Spring ones (and starting the mock server), but I'm not sure if this would work (I still don't know yet how I would pass the port to the container, I have never implemented such listeners).
Question: before I implement listeners or some other custom solution I wanted to make sure that I really need to. I searched the web a bit and didn't find anything, but I don't think we are the first team to write such tests, I'm just searching badly. Does anybody know of any kind of library that would solve this problem? Or maybe a neat Spring trick that I'm currently missing but one that would help?