在弹簧启动测试中使用线形随机端口设置属性

我有一个Spring Boot测试,它使用wiremock来模拟外部服务。为了避免与并行构建冲突,我不想为wiremock设置固定的端口号,而是希望依赖于其动态端口配置。

应用程序使用在 application.yml 中设置的属性 ()(在 src/test/resources 下)。但是,我没有找到一种方法来以编程方式覆盖它。我尝试过这样的东西:external.baseUrl

    WireMockServer wireMockServer = new WireMockServer();
    wireMockServer.start();
    WireMock mockClient = new WireMock("localhost", wireMockServer.port());
    System.setProperty("external.baseUrl", "http://localhost:" + wireMockServer.port());

但它不起作用,而是使用了 application.yml 中的值。我看过的所有其他解决方案都用静态值覆盖该属性(例如,在某些注释中),但在运行测试之前,我不知道wiremock端口的值。

澄清:

弹簧靴和线套都在随机端口上运行。这很好,我知道如何获得两个端口的价值。然而,wiremock应该模拟外部服务,我需要告诉我的应用程序如何访问它。我对酒店这样做。我想在测试中设置的值当然取决于 wiremock 端口号。我的问题只是如何在弹簧启动测试中以编程方式设置属性external.baseUrl


答案 1

考虑使用Spring Cloud Contract Wiremock

已经有一个JUnit规则构建器,它允许指定在属性/ yaml文件中设置随机端口${wiremock.port}

或者,您可以使用 将WireMock绑定到您的,这样您甚至不需要在测试中覆盖URL。WireMockRestServiceServerRestTemplate


答案 2

https://stackoverflow.com/a/48859553/309683 中提到的属性名称(即)不正确,至少自春季云合同版本以来是这样。wiremock.port2.1.2.RELEASE

1. 工作实例

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock;
import org.springframework.core.env.Environment;
import org.springframework.test.context.junit4.SpringRunner;

import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT)
@AutoConfigureWireMock(port = 0)
public class PortServiceTest {

    @Autowired
    private Environment environment;

    @Test
    public void shouldPopulateEnvironmentWithWiremockPort() {
        assertThat(environment.containsProperty("wiremock.server.port")).isTrue();
        assertThat(environment.getProperty("wiremock.server.port")).matches("\\d+");
    }

}

2. 其他 WireMock 特性

除 之外,还会使用一些其他属性填充环境:wiremock.server.port@AutoConfigureWireMock

  1. wiremock.server.https-port
  2. wiremock.server.stubs[]
  3. wiremock.server.files[]

3. Gradle 依赖关系

要在基于Gradle的项目中使用Spring Cloud Contract WireMock,请将以下依赖项添加到项目中:

testImplementation 'org.springframework.cloud:spring-cloud-contract-wiremock:${version}'

4. 在文件中使用application.yaml

如果像这样配置测试文件:application.yaml

sample:
  port: ${wiremock.server.port}

并定义以下豆类:

@Component
@ConfigurationProperties(prefix = "sample")
@Data
public class PortProperties {
    private Integer port;
}

@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class PortService {
    private final PortProperties config;

    public Integer getPort() {
        return config.getPort();
    }
}

您可以验证 是否设置为随机选择的 wiremock 端口:sample.port

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT)
@AutoConfigureWireMock(port = 0)
public class PortServiceTest {
    @Autowired
    private Environment environment;

    @Autowired
    private PortService portService;

    @Test
    public void shouldReturnWireMockPort() {
        assertThat(portService.getPort())
                .isNotNull()
                .isEqualTo(Integer.parseInt(environment.getProperty("wiremock.server.port")));
    }
}

推荐