一、参考
二、mock实践
前景: 本人作为步入职场的实习小白对于单元测试代码的编写就是加上以下两个注解@SpringBootTest
和 @RunWith(SpringRunner.class)
注解会促使启动spring容器,很多时候你会发现测试类启动过程很慢,你本质上只是想测试当前这个类的某些功能,但启动过程实际上是扫描了所有的bean;对于需要与外部其他开发人员对接接口时,想要在对接接口前保证自己编写程序的正确性,需要用什么方法呢 – mock完成单元测试
1、创建mock对象,定义对象接口方法的返回结果
//导入静态类代码编写更简易
import static org.mockito.Mockito.*;
//创建一个mock对象 依赖的某些接口可以通过mock的形式去完成,定义好想要的结果即可
Person p = mock(Person.class);
//当p的method方法被调用时,返回什么参数
when(p.method()).doReturn()
可以通过增加多个doReturn()
形式,表明第几次调用时返回什么;结果当方法没有返回值使用doNothing()
需要注意的是
模拟mock对象时,入参可以是参数匹配器,如果你使用参数匹配器,所有参数都必须由匹配器提供,如果采用确定的值 + 参数匹配器的混合,虽然编写的时候不会检索出错误,但运行就会报错,参数匹配器如 any()
相当于Java中的Object
, anyInt()
即是任意整数
verify(mock).someMethod(anyInt(), anyString(), eq("third argument"));
// 上述代码是正确的,因为eq()也是一个参数匹配器
verify(mock).someMethod(anyInt(), anyString(), "third argument");
//上诉代码错误,因为"third argument"不是一个参数匹配器
2、验证接口方法是不是被调用、被调用的次数
// mock creation 创建mock对象
List mockedList = mock(List.class);
//using mock object 使用mock对象
mockedList.add("one");
mockedList.add("twice");
mockedList.add("twice");
mockedList.add("three times");
mockedList.add("three times");
mockedList.add("three times");
verify(mockedList).add("once");
//⬆️ ⬇️这二者的效果是一样的
verify(mockedList, times(1)).add("once");
// 验证具体的执行次数
verify(mockedList, times(2)).add("twice");
verify(mockedList, times(3)).add("three times");
// 使用never()进行验证,never相当于times(0)
verify(mockedList, never()).add("never happened");
// 使用至少调用了几次atLeast()/ 最多调用了几次atMost()
verify(mockedList, atLeastOnce()).add("three times");
verify(mockedList, atLeast(2)).add("five times");
verify(mockedList, atMost(5)).add("three times");
3、Spy监控对象
mock是自定义方法,mock是模拟出一个对象,spy就是监控真实对象,通过spy调用到真实对象,你可以通过spy设计方法返回值,但实际上真实对象仍然被调用
如以下例子及运行结果所示便能很好体会这二者的区别:
List<String> mockList = mock(ArrayList.class);
mockList.add("one");
System.out.println("mockList 获取第一个元素" + mockList.get(0));
System.out.println("mockList 获取第二个元素" + mockList.get(1));
//需要你模拟出get方法的返回值才能返回正确
when(mockList.get(0)).thenReturn("one");
when(mockList.get(1)).thenReturn("two");
System.out.println("定义方法后的mockList 获取第一个元素" + mockList.get(0));
System.out.println("定义方法后的mockList 获取第二个元素" + mockList.get(1));
List<String> spyList = spy(ArrayList.class);
spyList.add("one");
System.out.println("spyList 获取第一个元素" + spyList.get(0));
System.out.println("spyList 获取第二个元素" + spyList.get(1));
运行结果: