《Java单元测试实战》——无效单测:那些年,我们写过的无效单元测试(8) https://developer.aliyun.com/article/1232107?groupCode=java
五、 验证抛出异常
异常作为Java语言的重要特性,是Java语言健壮性的重要体现。捕获并验证抛出异常,也是测试用例的一种。所以,在单元测试中,也需要对抛出异常进行验证。
1. 抛出异常来源方式
1) 来源于属性字段的判断
判断属性字段是否非法,否则抛出异常。

2) 来源于输入参数的判断
判断输入参数是否合法,否则抛出异常。

注意:这里采用的是Spring框架提供的Assert类,跟if-throw语句的效果一样。
3) 来源于返回值的判断
判断返回值是否合法,否则抛出异常。

4) 来源于模拟方法的调用
调用模拟的依赖方法时,可能模拟的依赖方法会抛出异常。

这里,可以进行异常捕获处理,或打印输出日志,或继续抛出异常。
5) 来源于静态方法的调用
有时候,静态方法调用也有可能抛出异常。

除此之外,还有别的抛出异常来源方式,这里不再累述。
2. 抛出异常验证方式
在单元测试中,通常存在四种验证抛出异常方法。
1) 通过try-catch语句验证抛出异常
Java单元测试用例中,最简单直接的异常捕获方式就是使用try-catch语句。

2) 通过@Test注解验证抛出异常
JUnit的@Test注解提供了一个expected属性,可以指定一个期望的异常类型,用来捕获并验证异常。

注意:测试用例在执行到 userService.createUser方法后将跳出方法,导致后续验证语句无法执行。所以,这种方式无法验证异常编码、消息、原因等内容,也无法验证依赖方法及其参数。
3) 通过@Rule注解验证抛出异常
如果想要验证异常原因和消息,就需求采用@Rule注解定义ExpectedException对象,然后在测试方法的前面声明要捕获的异常类型、原因和消息。

注意:测试用例在执行到userService.createUser方法后将跳出方法,导致后续验证语句无法执行。所以,这种方式无法验证依赖方法及其参数。由于ExpectedException的验证方法只支持验证异常类型、原因和消息,无法验证异常的自定义属性字段值。目前,JUnit官方建议使用Assert.assertThrows替换。
4) 通过Assert.assertThrows方法验证抛出异常
在最新版的JUnit中,提供了一个更为简洁的异常验证方式——Assert.assertThrows方法。

5) 四种抛出异常验证方式对比
根据不同的验证异常功能项,对四种抛出异常验证方式对比。结果如下:

综上所述,采用Assert.assertThrows方法验证抛出异常是最佳的,也是JUnit官方推荐使用的。
《Java单元测试实战》——无效单测:那些年,我们写过的无效单元测试(10) https://developer.aliyun.com/article/1232105?groupCode=java