Home > Software design >  Add environment property to @SpringBootTest before application.properties evaluation?
Add environment property to @SpringBootTest before application.properties evaluation?

Time:01-20

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?

CodePudding user response:

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);
}

CodePudding user response:

Maybe you prefer to start a single MockWebServer for all test classes, instead of starting a new server for each test method. When this class is initialized, the static block starts a server and sets a system property to the server URL. System properties override properties from the application.properties file.

@TestConfiguration
public class MockWebServerConfiguration {

  private static final MockWebServer mockWebServer = new MockWebServer();

  static {
    int port = SocketUtils.findAvailableTcpPort();
    mockWebServer.start(port);

    System.setProperty("web.client.url", "localhost:"   port   "/path");
  }
}

To include this configuration class in your integration test, annotate your test class with:

@Import(MockWebServerConfiguration.class)
  •  Tags:  
  • Related