1.概述
Java常用的单元测试框架有:Junit,TestNg,Easymock,Mockito,PowerMock。
本文主要讨论Mockito框架,是基于学习mockito文档和自己实操验证理解而来,mockito文档中文地址:https://github.com/hehonghui/mockito-doc-zh,感谢并向他们致敬。
开始之前,先谈谈对单元测试的理解,就不照搬普世定义了,只谈谈个人浅薄认识。
所谓单元测试unit test也叫打桩测试,我个人理解就是针对一个类或者说类中的一个方法,编写测试代码,在测试代码中做一些假设性的输入,断言被测试的代码是否能得出自己想要的逻辑结果。
写单元测试的好处,我个人工作经历认为比较明显的是:单元测试都跑过的代码,基本前后台联调没有问题;再者,对代码重构后,如果保持原来的输入输出不变,那么跑一遍单元测试,算是给自己吃颗定心丸。当然单元测试也有缺点,就是增加了工作代码量,需要花费程序员更多的时间,视项目具体情况而使用吧。
2.实操
实操之前记得导入mockito的jar包(import staticorg.mockito.Mockito.*; ),copy 然后alt+enter让maven自动增加就行:
image
或者把以下依赖增加到pom文件中:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
2.1 验证某些行为(方法)
一旦mock对象被创建了,mock对象会记住所有的交互。然后你就可能选择性的验证你感兴趣的交互。如果验证时,和使用中操作的不同,或者增加的对象不是一个,或者增加方法都会验证失败,如图所示:图片.png
2.2做测试桩 (Stub)
测试桩可以理解为对mock对象进行的一些预期操作,mock函数默认返回的是null。图片.png
2.2参数匹配器
参数匹配器指anyInt(),anyString()能代替复杂的参数匹配,让测试代码简洁。
when(mockedList.get(anyInt())).thenReturn("element");
verify(mock).someMethod(anyInt(), anyString(), eq("third argument"));
2.3验证确切verify(mock,time(x)).operate()、最少atLeast()/最多atMost()、从未调用never()
//mocklist .add 方法指只执行了一次
verify(mockedList, times(1)).add("once");
// 验证具体的执行次数ver
verify(mockedList, times(3)).add("three times");
// 使用never()进行验证,never相当于times(0)
verify(mockedList, never()).add("never happened");
//verification using atLeast()/atMost()
// 使用atLeast()/atMost()
verify(mockedList, atLeastOnce()).add("three times");
verify(mockedList, atLeast(2)).add("five times");
verify(mockedList, atMost(5)).add("three times");
2.4返回值为void的函数通过Stub抛出异常范式:doThrow(exception).when().operate()
doThrow(new RuntimeException()).when(mockedList).clear();
// 调用这句代码会抛出异常
mockedList.clear();
2.5验证执行顺序InOrder
List singleMock = mock(List.class);
singleMock.add("was added first");
singleMock.add("was added second");
// 为该mock对象创建一个inOrder对象
InOrder inOrder = inOrder(singleMock);
// 确保add函数首先执行的是add("was added first"),然后才是add("was added second")
inOrder.verify(singleMock).add("was added first");
inOrder.verify(singleMock).add("was added second");
// B. Multiple mocks that must be used in a particular order
// B .验证多个mock对象的函数执行顺序
List firstMock = mock(List.class);
List secondMock = mock(List.class);
//using mocks
firstMock.add("was called first");
secondMock.add("was called second");
//create inOrder object passing any mocks that need to be verified in order
// 为这两个Mock对象创建inOrder对象
InOrder inOrder = inOrder(firstMock, secondMock);
//following will make sure that firstMock was called before secondMock
// 验证它们的执行顺序
inOrder.verify(firstMock).add("was called first");
inOrder.verify(secondMock).add("was called second");
2.6确保交互(interaction)操作不会执行在mock对象上verifyZeroInteractions()
mockOne.add("one");
// 普通验证
verify(mockOne).add("one");
// 验证某个交互是否从未被执行
verify(mockOne, never()).add("two");
// 验证mock对象没有交互过
verifyZeroInteractions(mockTwo, mockThree);