AssertJ中assertThatCode()与assertThatThrownBy()的区别是什么?
AssertJ中
assertThatCode(…).isInstanceOf(…)与assertThatThrownBy(…).isInstanceOf(…)的区别 两者看似功能重叠,但核心设计意图和默认行为有明显差异:
1. 设计初衷与默认校验逻辑
assertThatThrownBy(…)是专门为验证“代码块必须抛出异常”而生的工具。它的第一逻辑就是校验代码块是否抛出了异常——如果没抛,断言直接失败,不会走到后续的isInstanceOf校验。只有代码块抛出了异常,才会继续验证异常类型是否匹配。assertThatCode(…)是通用的代码块断言工具,默认允许代码块正常执行不抛出异常。只有当你追加.isInstanceOf(…)这类异常校验时,它才会检查代码块是否抛出了指定类型的异常;如果没抛,断言才会失败。
2. 异常存在性的前置校验差异
用assertThatThrownBy(…).isInstanceOf(…)时,你不需要额外确认异常是否存在,方法本身就已经做了前置校验——它默认要求代码块必须抛出异常。而assertThatCode(…).isInstanceOf(…)只是在代码块执行后,校验“如果有异常,是否是指定类型”,同时也会校验“是否确实抛出了异常”。
3. 链式调用的语义合理性
你提到的assertThatThrownBy()支持doesNotThrowAnyException(),这是AssertJ提供的反向语义支持,但从命名和设计初衷看,这种用法非常反直觉——毕竟assertThatThrownBy的名字就指向“要抛出异常”,用它来验证不抛异常,远不如assertThatCode(…).doesNotThrowAnyException()语义清晰。
assertThatCode()的链式调用则更灵活,既可以验证异常(.isInstanceOf、.hasMessage(…)等),也可以验证代码块正常执行的结果(.returns(…)、.doesNotThrowAnyException()等),是一个全能型的代码块断言工具。
4. 实际运行差异示例
验证抛出指定异常
两段代码在正常抛出异常时结果一致:
// assertThatThrownBy写法 assertThatThrownBy(() -> riskyMethod("bad-input")) .isInstanceOf(IllegalArgumentException.class); // assertThatCode写法 assertThatCode(() -> riskyMethod("bad-input")) .isInstanceOf(IllegalArgumentException.class);
但如果riskyMethod("bad-input")没有抛出异常:
assertThatThrownBy会直接失败,提示:Expected code to throw an exception but it didn'tassertThatCode会失败,提示:Expecting code to throw an exception of type <java.lang.IllegalArgumentException> but it didn't throw any
验证不抛出异常
// 语义清晰的标准写法 assertThatCode(() -> safeMethod("good-input")) .doesNotThrowAnyException(); // 语义别扭但可运行的写法 assertThatThrownBy(() -> safeMethod("good-input")) .doesNotThrowAnyException();
内容的提问来源于stack exchange,提问作者Sergey Zolotarev
相关产品推荐
相关产品推荐

