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

如何Mock CompletableFuture.get()抛出异常以覆盖catch代码块

问题原因与解决方案

核心问题

  1. Mock对象未传入业务方法:你创建了spy但调用service.getStatus(futureA, futureB)时传的是原始的futureA,导致Mock的get()逻辑完全没生效。
  2. 未完成的Future导致阻塞:CompletableFuture.allOf().join()会等待所有传入的Future完成,而你创建的futureA是未完成状态,所以测试会一直阻塞在这里,根本到不了调用get()的逻辑。

解决方案

不需要用Mockito,直接通过CompletableFuture自身的completeExceptionally()方法让Future进入异常完成状态,就能触发catch代码块:

修改后的测试代码:

@Test
public void testException() {
    CompletableFuture<Object> futureA = new CompletableFuture<>();
    // 直接让futureA异常完成,触发get()时抛出异常
    futureA.completeExceptionally(new SomeException());
    CompletableFuture<Object> futureB = CompletableFuture.completedFuture(null);
    
    service.getStatus(futureA, futureB);
}

额外优化点

你的业务代码存在两个小问题:

  • CompletableFuture.allOf().join()已经等待所有Future完成,后续调用get()不会阻塞,但可以简化为用join()替代get(),避免检查受检异常(join()抛出RuntimeException,无需try-catch)
  • 方法没有默认返回值,会编译报错,建议最后添加return null;或其他默认值

修改后的业务代码示例:

public Object getStatus(CompletableFuture<Object> futureA, CompletableFuture<Object> futureB) {
    CompletableFuture.allOf(futureA, futureB).join();
    try {
        Object resultA = futureA.join();
        if(resultA != null) return resultA;
    } catch(CompletionException e) {
        // 这里捕获的是RuntimeException,实际异常可以通过e.getCause()获取SomeException
        // log
    }
    try {
        Object resultB = futureB.join();
        if(resultB != null) return resultB;
    } catch(CompletionException e) {
        // log
    }
    return null; // 添加默认返回值
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 15:12:48