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

新手求教:如何测试CompletableFuture.get()的中断与超时异常

测试CompletableFuture.get()的InterruptedException和TimeoutException

问题分析

你之前直接Mock CompletableFuture本身的思路走不通——CompletableFuture.allOf()会生成全新的Future实例,你Mock的对象根本不会被业务代码用到;而且failedFuture是模拟任务执行失败的场景,和超时、中断的触发逻辑完全不相关。

解决方案

1. 触发TimeoutException测试

要让get(30, TimeUnit.SECONDS)触发超时,核心是让allOf组合后的Future在30秒内无法完成。可以通过Mock客户端的post方法,让其返回一个永远阻塞或延迟超过超时时间的任务:

@Test
void shouldTriggerTimeoutException() {
    // Mock clientA.post,返回一个永远不会完成的Future
    when(clientA.post(anyString(), any(), any(ClassA.class)))
        .thenReturn(new CompletableFuture<>());
    // 同理处理clientB,或者只让其中一个阻塞即可触发整体超时
    when(clientB.post(anyString(), any(), any(ClassB.class)))
        .thenReturn(new CompletableFuture<>());

    // 执行你的业务方法
    YourService service = new YourService(clientA, clientB);
    service.yourBusinessMethod(language, json, a, b);

    // 验证超时逻辑:比如可以检查future是否被cancel,或对应日志是否输出
}

也可以用延迟执行器模拟超长时间的任务:

when(clientA.post(anyString(), any(), any(ClassA.class)))
    .thenApplyAsync(res -> res, CompletableFuture.delayedExecutor(40, TimeUnit.SECONDS));

2. 触发InterruptedException测试

要触发中断异常,需要在get()处于阻塞等待状态时,中断当前线程:

@Test
void shouldTriggerInterruptedException() throws InterruptedException {
    // 创建两个未完成的Future,让业务代码进入get()阻塞
    CompletableFuture<ClassA> futureA = new CompletableFuture<>();
    when(clientA.post(anyString(), any(), any(ClassA.class))).thenReturn(futureA);
    CompletableFuture<ClassB> futureB = new CompletableFuture<>();
    when(clientB.post(anyString(), any(), any(ClassB.class))).thenReturn(futureB);

    // 用单独线程执行业务方法
    Thread taskThread = new Thread(() -> {
        try {
            yourService.yourBusinessMethod(language, json, a, b);
        } catch (Exception ignored) {}
    });
    taskThread.start();

    // 等待一小会儿确保进入get()阻塞
    Thread.sleep(500);
    // 中断线程触发异常
    taskThread.interrupt();
    taskThread.join();

    // 验证逻辑:比如检查线程是否被重新中断,或对应错误日志是否输出
}

关键注意点

  • 不要Mock CompletableFuture本身:allOf()会生成新实例,Mock对象不会参与业务流程
  • 优先Mock底层依赖(clientA、clientB):更贴近真实业务场景,也更容易控制任务的执行状态

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 00:27:18