五、 注入依赖对象
当模拟完这些类成员对象后,我们需要把这些类成员对象注入到被测试类的实例中。以便在调用被测试方法时,可能使用这些类成员对象,而不至于抛出空指针异常。
1. 利用Setter方法注入
如果类定义了Setter方法,可以直接调用方法设置字段值。
2. 利用ReflectionTestUtils.setField方法注入
JUnit提供ReflectionTestUtils.setField方法设置属性字段值。
3. 利用Whitebox.setInternalState方法注入
PowerMock提供Whitebox.setInternalState方法设置属性字段值。
4. 利用@InjectMocks注解注入
@InjectMocks注解用来创建一个实例,并将其它对象(@Mock、@Spy或直接定义的对象)注入到该实例中。@InjectMocks注解需要配合@RunWith注解使用。
5. 设置静态常量字段值
有时候,我们需要对静态常量对象进行模拟,然后去验证是否执行了对应分支下的方法。比如:需要模拟Lombok的@Slf4j生成的log静态常量。但是,Whitebox.setInternalState方法和@InjectMocks注解并不支持设置静态常量,需要自己实现一个设置静态常量的方法:
具体使用方法如下:
注意:
经过测试,该方法对于int、Integer等基础类型并不生效,应该是编译器常量优化导致。
六、 模拟依赖方法
在模拟完依赖的参数和返回值后,就可以利用Mockito和PowerMock的功能,进行依赖方法的模拟。如果依赖对象还有方法调用,还需要模拟这些依赖对象的方法。
1. 根据返回模拟方法
1) 模拟无返回值方法
2) 模拟方法单个返回值
3) 模拟方法多个返回值
直接列举出多个返回值:
转化列表为多个返回值:
4) 模拟方法定制返回值
可利用Answer定制方法返回值:
5) 模拟方法抛出单个异常
指定单个异常类型:
指定单个异常对象:
6) 模拟方法抛出多个异常
指定多个异常类型:
指定多个异常对象:
7) 直接调用真实方法
2. 根据参数模拟方法
Mockito提供do-when语句和when-then语句模拟方法。
1) 模拟无参数方法
对于无参数的方法模拟:
2) 模拟指定参数方法
对于指定参数的方法模拟:
3) 模拟任意参数方法
在编写单元测试用例时,有时候并不关心传入参数的具体值,可以使用Mockito参数匹配器的any方法。Mockito提供了anyInt、anyLong、anyString、anyList、anySet、anyMap、any(Class<T> clazz)等方法来表示任意值。
4) 模拟可空参数方法
Mockito参数匹配器的any具体方法,并不能够匹配null对象。而Mockito提供一个nullable方法,可以匹配包含null对象的任意对象。此外,Mockito.any()方法也可以用来匹配可空参数。
5) 模拟必空参数方法
同样,如果要匹配null对象,可以使用isNull方法,或使用eq(null)。
6) 模拟不同参数方法
Mockito支持按不同的参数分别模拟同一方法。
注意:
如果一个参数满足多个模拟方法条件,会以最后一个模拟方法为准。
7) 模拟可变参数方法
对于一些变长度参数方法,可以按实际参数个数进行模拟:
也可以用Mockito.any()模拟一个通用匹配方法:
注意:
Mockito.<T>any()并不等于Mockito.any(Class<T> type),前者可以匹配null和类型T的可变参数,后者只能匹配T必填参数。