Add environment property to @SpringBootTest before application.properties evaluation?

Is it possible to add a "dynamic" property from a class to application.properties before they are evaluated?

I want to achieve the following: find a free port on the system, inject it as property mockPort into the spring lifecycle, and reuse this port to override a property from application.properties using @TestPropertySource, as follows:

@SpringBootTest
@TestPropertySource(properties = "web.client.url=localhost:${mockPort}/path")
public class MyWebTest {
               //TODO how to write the port into ${mockPort} property?
               private static final PORT = SocketUtils.findAvailableTcpPort();
 
               @BeforeEach
               public void init() {
                   MockWebServer mock = new MockWebServer();
                   mock.start(PORT);
               }
 
               @Test
               public void test() {
                   service.runWebRequest();
               }
}

The service under test can be any client that makes use of @Value("${web.client.url}). And as the free port is found dynamically during runtime, I have to somehow inject it into that property.

How can I achieve this?


Solution 1:

You can use Spring Framework's @DynamicPropertySource for this purpose. It's described in this blog post.

In the case of MyWebTest, the dynamic property source would look something like this:

@DynamicPropertySource
static void mockPortProperty(DynamicPropertyRegistry registry) {
    registry.add("mockPort", () -> PORT);
}