AssertJ assertThatCode与JUnit assertThrows表现差异及问题排查
断言(2)和(3)失败的原因解析
断言(2)失败的核心原因
hasCause(EmailAlreadyRegistered.class)是用来验证抛出异常的「根因异常」,而非抛出的异常本身。
你的业务代码中,registerCustomerUseCase.execute()直接抛出了EmailAlreadyRegistered异常——这个异常没有被任何其他异常包裹,它的cause属性是null。但你用hasCause断言时,是在期望这个异常存在一个类型为EmailAlreadyRegistered的原因,这和实际执行结果完全不符,所以断言失败。
如果想用assertThatCode验证抛出的异常类型,正确写法应该是:
assertThatCode(() -> registerCustomerUseCase.execute("Duplicated", "duplicated@mail.com", "pass")) .isInstanceOf(EmailAlreadyRegistered.class);
断言(3)失败的核心原因
doesNotThrowAnyException()的作用是验证代码块完全不抛出任何异常,但你的测试场景本身就是要触发EmailAlreadyRegistered异常,所以这个断言从逻辑上就和测试目标矛盾,必然会失败——这是测试断言的逻辑错误,而非框架问题。
额外说明
AssertJ的assertThatCode适用于两种场景:
- 验证代码无异常抛出,搭配
doesNotThrowAnyException(); - 验证代码抛出指定异常,此时需用
isInstanceOf、hasMessage等断言验证异常本身的属性,而非hasCause(除非你确实需要验证异常的嵌套原因)。
而assertThatExceptionOfType是AssertJ专门为异常验证设计的API,语义更直接,和JUnit的assertThrows作用一致,适合你当前的测试场景。
内容的提问来源于stack exchange,提问作者user3429660
相关产品推荐
相关产品推荐

