如何Mock CompletableFuture.get()抛出异常以覆盖catch代码块
问题原因与解决方案
核心问题
- Mock对象未传入业务方法:你创建了
spy但调用service.getStatus(futureA, futureB)时传的是原始的futureA,导致Mock的get()逻辑完全没生效。 - 未完成的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
相关产品推荐
相关产品推荐

