You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在集成测试中使用RestTemplate验证Wiremock的Fault代码?

验证Spring Cloud Contract Stub的Fault代码

看起来你在测试Spring Cloud Contract Stub的Fault场景时遇到了点小问题——毕竟Fault和普通的HTTP状态码验证逻辑不太一样,我来给你捋清楚怎么处理。

首先得明确一个关键:当你给Stub配置了withFault(Fault.MALFORMED_RESPONSE_CHUNK)这类规则时,Stub不会返回正常的ResponseEntity。它会模拟一个异常的响应(比如格式错误的分块响应),导致你的RestTemplate.postForEntity()调用直接抛出异常,而不是返回一个可用的响应对象。这也是你原代码里assertThat(actualResponse, is(fault))无法工作的原因——actualResponse根本不会被正常赋值。

接下来是具体的解决方案,分两步走:

1. 捕获Stub触发的异常并验证Fault类型

你需要修改测试逻辑,从“获取响应后断言”改成“捕获预期异常并验证异常类型”。不同的Fault枚举值会触发不同的客户端异常,比如MALFORMED_RESPONSE_CHUNK会导致MalformedChunkCodingException(被RestClientException包装)。

修改后的测试代码示例:

@Test
public void shouldReturnSuitableStatusCodeForScenario(String requestFileName, Fault expectedFault, String actualResponseFileName) throws JSONException { 
    // Given 
    String createRequest = readJsonFromFile(DIRECTORY, requestFileName); 

    // When & Then
    Assertions.assertThrows(RestClientException.class, () -> {
        // 调用Stub,预期会抛出异常
        stub.postForEntity(HTTP_LOCALHOST_8081 + "/v1/transaction/", createRequest, String.class);
    }, "Expected a fault of type " + expectedFault + " but no exception was thrown");

    // 进一步验证具体的异常类型,匹配预期的Fault
    try {
        stub.postForEntity(HTTP_LOCALHOST_8081 + "/v1/transaction/", createRequest, String.class);
        fail("Exception was expected but not thrown");
    } catch (RestClientException ex) {
        switch (expectedFault) {
            case MALFORMED_RESPONSE_CHUNK:
                assertThat(ex.getCause(), instanceOf(MalformedChunkCodingException.class));
                break;
            case CONNECTION_RESET:
                assertThat(ex.getCause(), instanceOf(ConnectionResetException.class));
                break;
            case BAD_GATEWAY:
                // 对应BadGatewayException或类似异常,根据你的客户端实现调整
                assertThat(ex, instanceOf(HttpServerErrorException.BadGateway.class));
                break;
            default:
                fail("Unsupported fault type: " + expectedFault);
        }
    }
}

2. 关于响应体的验证(可选)

需要注意:部分Fault场景下,Stub返回的响应本身是格式错误的(比如MALFORMED_RESPONSE_CHUNK),RestTemplate根本无法正常解析响应体,所以你原代码里的JSONAssert.assertEquals()可能无法执行。

如果确实需要验证Stub返回的原始响应内容,你可以给RestTemplate添加一个拦截器,在异常发生前捕获原始的响应数据:

@BeforeEach
void setUp() {
    stub = new RestTemplate();
    // 添加拦截器捕获原始响应
    stub.getInterceptors().add((request, body, execution) -> {
        ClientHttpResponse response = execution.execute(request, body);
        // 记录原始响应内容到变量,方便后续验证
        String rawBody = StreamUtils.copyToString(response.getBody(), StandardCharsets.UTF_8);
        // 注意:这里需要把响应体重新包装回去,否则后续处理会报错
        response = new BufferingClientHttpResponseWrapper(response);
        // 可以把rawBody存到测试类的成员变量里
        this.lastRawResponse = rawBody;
        return response;
    });
}

不过要注意,像MALFORMED_RESPONSE_CHUNK这类Fault,原始响应本身就是不符合规范的,所以响应体的验证意义不大,重点还是放在异常类型的匹配上。

最后再总结一下核心要点:

  • Fault场景的核心是验证客户端抛出的异常类型,而非正常响应的状态码或体
  • 不同的Fault枚举对应不同的客户端异常,需要根据实际情况调整断言逻辑
  • 部分Fault场景下无法正常解析响应体,建议优先验证异常而非响应内容

内容的提问来源于stack exchange,提问作者Coder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 21:47:46