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

如何移除Java Optional的ifPresent中assertThat语句的try-catch块

解决方案

核心原因是ifPresent接收的Consumer函数式接口的accept方法不允许抛出受检异常,你代码中json.write()和objectMapper.writeValueAsString()都会抛出受检的IOException,因此编译器强制要求你在lambda内部捕获异常,不允许向上抛出。

以下是两种可直接落地的方案:

方案1:替换ifPresent为显式判空(最推荐,无额外代码侵入)

放弃lambda形式的ifPresent,改用isPresent()判断后手动取值,此时代码块不属于Consumer接口约束范围,你的测试方法已经声明了throws IOException,可直接移除内层try-catch:

@Test
public void testPostRequestThenSaveResponse()
        throws HttpStatusCodeException, JsonProcessingException, IllegalArgumentException, IOException {
    // Should success.
    try {
        // 先接收Optional返回值
        var responseOpt = ServiceAssignmentImpl.httpPostDeliveryOrder(url, token, sod, customerSite, customer, item, uom, driver);
        // 显式判空后处理
        if (responseOpt.isPresent()) {
            DeliveryOrderResponse deliveryOrderResponse = responseOpt.get();
            // increase DO number for next test.
            deliveryOrderNum++;
            DeliveryOrderResponse savedDOResponse = deliveryOrderResponseRepository
                    .save(deliveryOrderResponse);
            DeliveryOrderResponse fetchedDOResponse = deliveryOrderResponseRepository
                    .findOne(savedDOResponse.getId());
            // 直接写断言,不需要try-catch,异常直接向上抛出
            assertThat(json.write(fetchedDOResponse))
                    .isEqualTo(objectMapper.writeValueAsString(deliveryOrderResponse));
        }
    } catch (HttpStatusCodeException e) {
        // need getResponseBodyAsString() to see detail error message.
        System.out.println("** HttpStatusCodeException: " + e.getResponseBodyAsString());
        throw e;
    }
}

如果使用Java 8/9版本,将代码中的var responseOpt替换为Optional<DeliveryOrderResponse> responseOpt即可。

这个方案同时解决了原代码的隐藏问题:原代码内层catch仅打印堆栈不抛出异常,如果序列化步骤报错,测试不会标记失败,仅会打印日志,属于漏测问题。

方案2:包装受检异常为非受检异常(保留ifPresent写法)

如果你坚持要使用ifPresent的lambda形式,可以在catch块中将IOException包装为非受检的RuntimeException抛出,此时不需要额外修改方法签名:

// ifPresent内部的断言部分改写为
try {
    assertThat(json.write(fetchedDOResponse))
            .isEqualTo(objectMapper.writeValueAsString(deliveryOrderResponse));
} catch (IOException e) {
    throw new RuntimeException("序列化对比失败", e);
}

注意:原代码中catch块仅打印异常不抛出的写法是错误的,会导致序列化异常时测试不会失败,无论选哪种方案都建议将异常向上抛出,让JUnit可以正确标记测试失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 12:36:03