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

Java 8 Lambda表达式无法触发异常,单元测试未失败原因咨询

问题分析与解决方案

这是个很常见的CompletableFuture新手坑——问题出在异步回调的异常不会自动传播到你的单元测试主线程上,我来帮你拆解清楚:

为什么单元测试没捕获到异常?

  • 你在thenAcceptBoth里写的校验逻辑是运行在异步线程中的,和单元测试执行的主线程完全分离。
  • 你的单元测试方法会在调用verifyingIndividualSubmissionValueLimits后直接执行完毕,根本不会等待异步回调的执行——也就是说,异步任务还没来得及抛出异常,测试就已经标记为“通过”了。
  • 更关键的是:CompletableFuture的异步回调里抛出的异常,默认会被Future对象“吞掉”,除非你主动调用join()/get()方法来触发异常传播。

怎么修复让单元测试能捕获到异常?

最简单的方案是修改你的方法,让它返回CompletableFuture实例,然后在单元测试中主动等待任务完成并捕获异常。

第一步:修改业务方法返回CompletableFuture

public CompletableFuture<Void> verifyingIndividualSubmissionValueLimits(String alias, double min, double max) {
    // ... 部分代码省略 ...
    CompletableFuture<Double> localPriceFuture = instrumentRequester.getMidPrice(instId);
    // 将thenAcceptBoth的结果返回给调用方
    return localPriceFuture.thenAcceptBoth(dollarFxRateFuture, (localPrice, fxRate) -> {
        double minLocalValue = min * fxRate;
        double maxLocalValue = max * fxRate;
        long minQuantity = Math.round(minLocalValue / localPrice);
        long maxQuantity = Math.round(maxLocalValue / localPrice);
        if (subQty < minQuantity || subQty > maxQuantity) {
            log.debug("We should throw an exception because subQty is {}", subQty);
            throw new SubmissionValidationException(String.format("Quantity: %s, is not within %s and %s", subQty, minQuantity, maxQuantity));
        }
    });
}

第二步:修改单元测试等待异步任务并捕获异常

@Test(expected = SubmissionValidationException.class)
public void testSubmissionQuantityOutOfRange() {
    // 调用方法获取Future
    CompletableFuture<Void> validationFuture = yourService.verifyingIndividualSubmissionValueLimits("testAlias", 182, 255);
    // 调用join()等待异步任务完成,异常会被抛出到主线程
    validationFuture.join();
}

其他可选方案

如果你的业务场景不适合返回Future,也可以在单元测试中用CountDownLatch来手动等待异步任务完成:

@Test(expected = SubmissionValidationException.class)
public void testSubmissionQuantityOutOfRange() throws InterruptedException {
    CountDownLatch latch = new CountDownLatch(1);
    // 可以在回调的finally里调用latch.countDown(),或者用handle方法处理结果/异常
    yourService.verifyingIndividualSubmissionValueLimits("testAlias", 182, 255);
    // 等待最多5秒(根据实际情况调整)
    latch.await(5, TimeUnit.SECONDS);
}

不过这种方式不如返回Future+join()优雅,推荐优先用第一种方案。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:13:57