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

如何在集成测试中获取并验证EllaService异步调用返回的ServiceResponse

解决方案:捕获异步调用的返回结果

要验证connector.call()的异步返回结果,核心是让你的异步方法返回一个可追踪的Future类型,而不是void。下面是具体的修改步骤:

1. 调整EllaService的方法签名与逻辑

首先修改invokeEllaAsync方法,让它返回CompletableFuture<ServiceResponse<EllaResponseDto>>,同时调整callEllaService方法返回实际的响应结果,这样异步任务可以把结果传递出来:

@Service
public class EllaService {
    // ... 原有的成员变量与initialize方法保持不变

    // 修改异步方法的返回类型为CompletableFuture
    @Async(ELLA_THREAD_POOL_EXECUTOR_NAME)
    public CompletableFuture<ServiceResponse<EllaResponseDto>> invokeEllaAsync(final IrisBo irisBo) {
        if (isTrafficAllowed(irisBo)) {
            // 调用callEllaService并返回结果包装的Future
            return CompletableFuture.completedFuture(callEllaService(irisBo));
        } else {
            // 流量不允许时,返回一个标记为成功的空响应(或根据业务需求调整)
            return CompletableFuture.completedFuture(ServiceResponse.success(null));
        }
    }

    // 修改该方法返回ServiceResponse,而不是void
    public ServiceResponse<EllaResponseDto> callEllaService(final IrisBo irisBo) {
        HttpHeaders ellaHeaders = createRequestHeaders(irisBo);
        ServiceResponse<EllaResponseDto> response = connector.call(EllaDtoConverter.convertToRequest(irisBo), ellaHeaders);
        if (!response.isSuccess()) {
            LOG.error("ERROR occured while calling ella async [ irisBo: {} - response: {}]", irisBo, response);
        }
        // 返回响应结果
        return response;
    }

    // ... 原有的isTrafficAllowed、isShopNotConfigured、createRequestHeaders方法保持不变
}

2. 修改集成测试类,捕获并验证异步结果

在测试中,我们可以通过CompletableFuture的get()或join()方法等待异步任务完成,然后直接验证返回的ServiceResponse:

public class EllaServiceIT {
    // ... 原有的成员变量、WireMockRule、setUp方法保持不变

    @Test
    public void testCallEllaServiceIsSuccessful() throws Exception {
        // 模拟Ella服务返回成功响应
        wireMockRule.stubFor(post(urlEqualTo(ELLA_ENDPOINT))
                .willReturn(aResponse()
                        .withStatus(200)
                        .withHeader("Content-Type", MediaType.APPLICATION_JSON_UTF8_VALUE)
                        .withBody("{\"someField\": \"testValue\"}"))); // 根据EllaResponseDto的结构构造模拟响应

        // 调用异步方法并获取Future
        CompletableFuture<ServiceResponse<EllaResponseDto>> future = ellaService.invokeEllaAsync(irisBo);
        // 等待任务完成(设置超时避免无限等待)
        ServiceResponse<EllaResponseDto> response = future.get(5, TimeUnit.SECONDS);

        // 验证响应结果
        assertTrue("调用Ella服务应该成功", response.isSuccess());
        assertNotNull("响应DTO不应为空", response.getBody());
        // 可以根据EllaResponseDto的字段进一步验证,比如:
        // assertEquals("testValue", response.getBody().getSomeField());

        // 同时验证WireMock收到了请求
        verify(exactly(1), postRequestedFor(urlEqualTo(ELLA_ENDPOINT)));
    }

    @Test
    public void testCallEllaServiceIsUnsuccessful() throws Exception {
        // 模拟Ella服务返回500错误
        wireMockRule.stubFor(post(urlEqualTo(ELLA_ENDPOINT))
                .willReturn(serverError()));

        CompletableFuture<ServiceResponse<EllaResponseDto>> future = ellaService.invokeEllaAsync(irisBo);
        ServiceResponse<EllaResponseDto> response = future.get(5, TimeUnit.SECONDS);

        // 验证响应标记为失败
        assertFalse("调用Ella服务应该失败", response.isSuccess());
        // 可以进一步验证错误信息(如果ServiceResponse包含错误码/消息)
        // assertEquals("INTERNAL_ERROR", response.getErrorCode());

        // 验证WireMock收到了请求(即使返回错误,请求还是会发送的,原测试的verify(0)是错误的!)
        verify(exactly(1), postRequestedFor(urlEqualTo(ELLA_ENDPOINT)));
    }
}

关键说明

  • 为什么返回CompletableFuture?:Spring的@Async支持返回CompletableFuture,它提供了丰富的异步操作API,能让我们方便地等待任务完成、处理结果或异常。
  • 原测试的错误点:在testCallEllaServiceIsUnsuccessful中,原代码期望verify(0)是错误的——即使Ella返回500,请求依然会被发送,只是ServiceResponse标记为失败,所以应该验证exactly(1)次请求。
  • 超时设置:使用future.get(5, TimeUnit.SECONDS)可以避免测试因异步任务卡住而无限等待,建议根据实际业务超时时间调整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:40:52