在 application.properties 评估之前将环境 属性 添加到 @SpringBootTest?

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

是否可以在评估之前从 class 到 application.properties 添加“动态”属性?

我想实现以下目标:在系统上找到一个空闲端口,将其作为 属性 mockPort 注入到 spring 生命周期中,并重用此端口来覆盖 属性 来自 application.properties 使用 @TestPropertySource,如下:

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

被测服务可以是任何使用@Value("${web.client.url})的客户端。由于空闲端口是在运行时动态找到的,我必须以某种方式将它注入 属性.

我怎样才能做到这一点?

您可以使用 Spring 框架的 @DynamicPropertySource 来达到这个目的。 this blog post.

中对此进行了描述

MyWebTest 的情况下,动态 属性 源看起来像这样:

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

也许您更愿意为所有测试 class 启动一个 MockWebServer,而不是为每个测试方法启动一个新服务器。初始化此 class 时,静态块会启动服务器并将系统 属性 设置为服务器 URL。 System properties override 属性来自 application.properties 文件。

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

要在您的集成测试中包含此配置 class,请将您的测试 class 注释为:

@Import(MockWebServerConfiguration.class)