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

求助:如何覆盖公共方法中CompletableFuture的exceptionally分支?

如何覆盖CompletableFuture的exceptionally分支

第一步:修正原代码的致命错误

原代码里exceptionally分支调用aFuture.get()是逻辑错误——aFuture就是当前正在执行的CompletableFuture实例,此时它处于未完成状态,调用get()会导致无限阻塞。必须改为调用第二个Future实例aFuture1.get():

CompletableFuture<Optional<A>> aFuture = CompletableFuture.supplyAsync(() -> Optional.ofNullable(service.getA("As")))
    .exceptionally((ex) -> {
        log.error("Exception Happen Fetching from another source");
        CompletableFuture<Optional<A>> aFuture1 = CompletableFuture.supplyAsync(() -> Optional.ofNullable(service.getAAsB("As")))
            .exceptionally((ex2) -> {
                log.error("Exception Happen Fetching from another source also failed");
                return Optional.empty();
            });
        try {
            // 修正:调用aFuture1.get()而非aFuture.get()
            return aFuture1.get();    
        } catch(Exception exa) {
            throw new RuntimeException(exa);
        }
    });

第二步:编写测试用例覆盖分支

覆盖第一个exceptionally分支(首次调用失败)

用Mock框架(如Mockito)模拟service.getA("As")抛出异常,同时让getAAsB返回正常结果:

// 初始化Mock
Service service = Mockito.mock(Service.class);
// 让第一次调用抛出异常
Mockito.when(service.getA("As")).thenThrow(new RuntimeException("测试异常"));
// 让备用调用返回有效实例
Mockito.when(service.getAAsB("As")).thenReturn(new A());

// 执行目标逻辑
CompletableFuture<Optional<A>> future = 你的测试类.目标方法(service);
Optional<A> result = future.join();

// 验证逻辑触发
Assert.assertTrue(result.isPresent());
Mockito.verify(service).getA("As");
Mockito.verify(service).getAAsB("As");

覆盖第二个exceptionally分支(两次调用都失败)

同时模拟两次调用都抛出异常:

Service service = Mockito.mock(Service.class);
Mockito.when(service.getA("As")).thenThrow(new RuntimeException("第一次调用异常"));
Mockito.when(service.getAAsB("As")).thenThrow(new RuntimeException("备用调用异常"));

CompletableFuture<Optional<A>> future = 你的测试类.目标方法(service);
Optional<A> result = future.join();

// 验证结果为空,且两次调用都被触发
Assert.assertTrue(result.isEmpty());
Mockito.verify(service).getA("As");
Mockito.verify(service).getAAsB("As");

额外提示

  • 测试时优先用CompletableFuture.join()替代get(),无需处理受检异常,简化代码。
  • 如果测试中Future持续阻塞,检查是否存在循环等待的逻辑错误(比如原代码的aFuture.get()问题)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 21:40:21