mockito学习笔记
2017-12-21 本文已影响235人
crossroads
前言
根据中文版mockito与英文版mockito的教程学习笔记。
这里只有基础的一些,更深的目前没有用到,也就没写了,大家直接进链接看吧!
一、验证某些行为
一旦mock对象被创建了,mock对象会记住所有的交互。
@Test
@DisplayName("验证某些行为")
void verifyBehavior() {
//创建mockito对象
List mockedList = mock(List.class);
mockedList.add("one");
mockedList.clear();
//验证行为
verify(mockedList).add("one");
verify(mockedList).clear();
}
二、测试桩
@Test
void stubbing() {
List mock = mock(ArrayList.class); //默认情况下,所有的函数都有返回值。mock函数默认返回的是null,一个空的集合或者一个被对象类型包装的内置类型,例如0、false对应的对象类型为Integer、Boolean
System.out.println(mock + "--" + mock.size()); //输出Mock for ArrayList, hashCode: 480490520--0
mock.add(0, "win");
when(mock.get(0)).thenReturn("first"); //一旦测试桩函数被调用,该函数将会一致返回固定的值
System.out.println(mock.get(0)); //输出first
when(mock.get(0)).thenReturn("first change");
when(mock.get(1)).thenReturn(new IndexOutOfBoundsException());
System.out.println(mock.get(0)); //输出second
System.out.println(mock.get(1)); //输出java.lang.IndexOutOfBoundsException
//get(2) 没有打桩
System.out.println(mock.get(2)); //输出null
}
三、参数匹配器
@Test
void argumentMatchers() {
List mock = mock(ArrayList.class);
when(mock.get(anyInt())).thenReturn("element");
System.out.println(mock.get(10086));//输出element
}
四、验证函数的调用次数
@Test
void verifyExactNumber() {
List mockedList = mock(List.class);
mockedList.add("once");
mockedList.add("twice");
mockedList.add("twice");
verify(mockedList, times(1)).add("once"); //执行了一次
verify(mockedList, times(2)).add("twice");//执行了两次
verify(mockedList, never()).add("never");
verify(mockedList,atLeastOnce()).add("twice");
verify(mockedList,atLeast(2)).add("twice");
verify(mockedList,atMost(2)).add("twice");
}
五、抛出异常
@Test
void throwExceptions(){
List mockedList = mock(List.class);
// doThrow(new RuntimeException()).when(mockedList).clear();
doThrow(new RuntimeException()).when(mockedList).contains(anyInt());
// mockedList.clear(); //抛出java.lang.RuntimeException异常
mockedList.contains(1); //抛出java.lang.RuntimeException异常
}
六、确保交互操作不会执行在mock对象上
@Test
void makeSureInteractionsNeverHappened(){
List mockedList = mock(List.class);
List mockedList2 = mock(List.class);
mockedList.addAll(mockedList2);
verifyZeroInteractions(mockedList,mockedList2);//抛出org.mockito.exceptions.verification.NoInteractionsWanted异常
}
七、验证执行顺序
@Test
void verificationInOrder(){
List mockedList = mock(List.class);
mockedList.add("first");
mockedList.add("second");
InOrder inOrder = inOrder(mockedList);
inOrder.verify(mockedList).add("first");
inOrder.verify(mockedList).add("second");
List firstMockedList = mock(List.class);
List secondMockedList = mock(List.class);
firstMockedList.add("first");
secondMockedList.add("first");
InOrder multipleOrder = inOrder(firstMockedList, secondMockedList);
multipleOrder.verify(firstMockedList).add("first");
multipleOrder.verify(secondMockedList).add("first");
verifyZeroInteractions(mockedList,firstMockedList,secondMockedList);
}
八、查找冗余的调用
即验证传入的这些mock对象是否存在没有验证过的调用方法
@Test
void findRedundantInvocations() {
List mockedList = mock(List.class);
mockedList.add("one");
verifyNoMoreInteractions(mockedList);//抛出org.mockito.exceptions.verification.NoInteractionsWanted异常
}
verifyNoMoreInteractions()在交互测试套件中只是一个便利的验证,它的作用是当你需要验证是否存在冗余调用时。滥用它将导致测试代码的可维护性降低,所以不建议过于频繁的在每个测试方法中都使用。
九、简化mock对象的创建
@Mock
private ArrayList mockedList;
@BeforeEach
void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
void verifyBehavior() {
mockedList.add("one");
verify(mockedList).add("one");
}
十、为连续的调用做测试桩
@Test
void stubbingConsecutiveCalls(){
when(mockedList.get(0)).thenReturn("first").thenReturn("second");
//也可以这样写
// when(mockedList.get(0)).thenReturn("first","second");
System.out.println(mockedList.get(0)); //输出first
System.out.println(mockedList.get(0)); //输出second
}
等价于
doReturn("first","second").when(mockedList).get(0);
System.out.println(mockedList.get(0)); //输出first
System.out.println(mockedList.get(0)); //输出second
这两种方式还是有区别的,我们在十一条中讲。
十一、局部mocks(1.8.0+支持)
@Test
void realPartialMocks(){
when(mockedList.get(10)).thenCallRealMethod(); //将会调用真实的方法
System.out.println(mockedList.get(10));
}
在一些罕见的情况下部分测试才会是易用的:处理不能轻易修改的代码(第三方接口,临时重构的遗留代码等等)。然而,为了新的,测试驱动和架构优秀的代码,我是不会使用部分测试的。
十二、重置mocks对象
reset(mockedList);
十三、小技巧~模板代码
val eventLogicStub: EventLogic
get() = mock(EventLogic::class.java).apply {
doReturn(Observable.just(events))
.`when`(this)
.getEventsXX(anyString(), anyBoolean())
doReturn(Single.just(events))
.`when`(this)
.getEventXX(anyString(), anyBoolean())
doReturn(Single.just(files))
.`when`(this)
.getFilesXXX(anyString(), anyBoolean())
doReturn(Maybe.just(files))
.`when`(this)
.getFileXX(anyString(), anyBoolean())
......
}
这样子一个个重复劳动该怎么省去呢?用代码模板,我的是这样的:
输入dro,就可以得到如下的代码↓
自定义快捷输入
如何做?如何写?如下图
模板代码
如果你看到如下这样的提示,点击define,选择所在的组,例如我的是kotlin
文件,就选择kotlin啦