如何使用 RestAssured 在 Spring Boot 集成测试中为客户端调用设置端口?

问题描述

我正在努力为我的应用程序编写适当的集成测试。我使用放心和 Maven 故障安全插件。 目前我收到这样的异常:

org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://localhost/api/deactivate/1": Connect to localhost:80 [localhost/127.0.0.1] Failed: Connection refused (Connection refused); nested exception is org.apache.http.conn.HttpHostConnectException: Connect to localhost:80 [localhost/127.0.0.1] Failed: Connection refused (Connection refused)

我的假设是 url 中缺少端口 (8080) 有问题。然而我不知道为什么。 我有两个模块,一个正在调用一个。第一个运行在 8081 端口,第二个运行在 8080 端口。

这是模块 1 的测试配置(模块 2 配置类似但另一个端口)。我的测试扩展了这个类:

public abstract class AbstractDeactivationIT {

    @BeforeAll
    public static void configureRestAssured() {
        RestAssured.port = Integer.parseInt(System.getProperty("it.deactivation.port","8081"));
        System.out.println("RestAssured: using port " + RestAssured.port);

        // authentication config
        
        ...

        var mapper = ObjectMapperFactory.defaultConfig().build();

        RestAssured.config = RestAssured.config()
                .logConfig(logConfig().enableLoggingOfRequestAndResponseIfValidationFails())
                .objectMapperConfig(objectMapperConfig().jackson2ObjectMapperFactory((type,s) -> mapper));
    }
}

我的测试:

@Test
void testDeactivation_forCorrectRequestData() {
    // @formatter:off
    given()
        .contentType(JSON)
        .body(DeactivationRequest.builder()
            ...
            .build()
        ).
    when()
        .post("/api/deactivations").
    then()
        .statusCode(201);
    // @formatter:on
}

在调试时,我注意到第一个调用是正确构建的(使用端口 8081),但客户端调用没有 8080 端口。我的 application-local.yml 文件中有两个带有端口的 URL。我也有类似的测试,但方向相反,所以模块 2 正在调用模块 1,并且工作正常,没有任何端口问题。网址构建正确。

解决方法

RestAssured.port 是一个静态字段。如果您在相同的故障安全配置中运行两个测试,那么测试的顺序可能会与静态属性混淆。

不要使用静态 RestAssured 配置,而是为每个 RestAssured 调用构造带有端口的正确 url。

您可以使用带有 url 而不是相对路径的 get()post() 等方法(例如:.when().get("http://myhost.org:80/doSomething");)。来源:https://github.com/rest-assured/rest-assured/wiki/Usage#default-values

在你的情况下可能是:

given()
    .contentType(JSON)
    .body(DeactivationRequest.builder()
        ...
        .build()
    ).
when()
    .post("http://localhost:8081/api/deactivations").
then()
    .statusCode(201);