基本介绍
什么是 Mock 测试
Mock 测试就是在测试过程中,对于某些不容易构造(如 HttpServletRequest 必须在Servlet 容器中才能构造出来)或者不容易获取比较复杂的对象(如 JDBC 中的ResultSet 对象),用一个虚拟的对象(Mock 对象)来创建以便测试的测试方法。
Mock 最大的功能是帮你把单元测试的耦合分解开,如果你的代码对另一个类或者接口有依赖,它能够帮你模拟这些依赖,并帮你验证所调用的依赖的行为。
比如一段代码有这样的依赖:
当我们需要测试A类的时候,如果没有 Mock,则我们需要把整个依赖树都构建出来,而使用 Mock 的话就可以将结构分解开,像下面这样:
在哪里使用Mock对象?
- 真实对象很难被创建的
- 真实对象的某些行为很难被触发
- 真实对象实际上还不存在的(正在开发中)等等
一、添加依赖
<!--mockito框架-->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.5.15</version>
<scope>test</scope>
</dependency>
如果在导包时报错,删掉上面的scope作用域标签
1.验证行为
@Test
public void test1() {
// 可以模拟一个接口
List mockedList = mock(List.class);
// 然后可以直接使用接口的方法
mockedList.add("one");
mockedList.clear();
//verification 验证是否发生某种行为,发生了,啥都不做,未发生,报错
// 下面这句会报错,因为 add的是one而不是two
// verify(mockedList).add("two");
verify(mockedList).clear();
}
2.模拟一个实体类
@Test
public void test2() {
// mock一个具体的类,产生mock后的对象
LinkedList mockedList = mock(LinkedList.class);
when(mockedList.get(0)).thenReturn("first");
when(mockedList.get(1)).thenThrow(new RuntimeException("我自己抛出的异常"));
// following prints "first"
System.out.println(mockedList.get(0));
// following throws runtime exception
// System.out.println(mockedList.get(1));
// null 因为没有存过999
System.out.println(mockedList.get(999));
mockedList.add("11111");
// 猜想:因为不是真实对象,所以size()始终为 0
System.out.println(mockedList.size());
// 验证调用了get(0)
verify(mockedList).get(0);
}
3.参数匹配器
@Test
public void test3() {
// mock一个具体的类,产生mock后的对象
LinkedList mockedList = mock(LinkedList.class);
//stubbing using built-in anyInt() argument matcher
when(mockedList.get(anyInt())).thenReturn("element");
when(mockedList.contains(argThat(new Matches("ssss")))).thenReturn(true);
// 可以使用正则表达式,没搞清楚怎么用的,下面返回true
System.out.println(mockedList.contains("ssss"));
//following prints "element"
System.out.println(mockedList.get(999));
//you can also verify using an argument matcher
verify(mockedList).get(anyInt());
}
4.验证方法调用的次数
@Test
public void test4() {
// mock一个具体的类,产生mock后的对象
LinkedList mockedList = mock(LinkedList.class);
mockedList.add("once");
mockedList.add("twice");
mockedList.add("twice");
mockedList.add("three times");
mockedList.add("three times");
mockedList.add("three times");
//following two verifications work exactly the same - times(1) is used by default
verify(mockedList).add("once");
verify(mockedList, times(1)).add("once");
//exact number of invocations verification
verify(mockedList, times(2)).add("twice");
verify(mockedList, times(3)).add("three times");
//verification using never(). never() is an alias to times(0)
verify(mockedList, never()).add("never happened");
// 验证最少、最多调用的次数
verify(mockedList, atLeastOnce()).add("three times");
// verify(mockedList, atLeast(2)).add("five times");
verify(mockedList, atMost(5)).add("three times");
}
5.模拟方法抛出异常
@Test
public void test5() {
// mock一个具体的类,产生mock后的对象
LinkedList mockedList = mock(LinkedList.class);
doThrow(new RuntimeException("我就抛出异常了")).when(mockedList).clear();
//调用的时候就会抛出异常
mockedList.clear();
}
6.验证方法调用的顺序
@Test
public void test6() {
// A. Single mock whose methods must be invoked in a particular order
List singleMock = mock(List.class);
//using a single mock
singleMock.add("was added first");
singleMock.add("was added second");
//create an inOrder verifier for a single mock
InOrder inOrder = inOrder(singleMock);
// 验证方法调用的顺序, 如果下面列出的顺序和调用的顺序一样,则通过,否则抛出异常
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
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
InOrder inOrder2 = inOrder(firstMock, secondMock);
//following will make sure that firstMock was called before secondMock
inOrder2.verify(firstMock).add("was called first");
inOrder2.verify(secondMock).add("was called second");
}
7.确保 mock 上不会发生交互
@Test
public void test7() {
List mockOne = Mockito.mock(List.class);
List mockTwo = Mockito.mock(List.class);
List mockThree = Mockito.mock(List.class);
// using mocks - only mockOne is interacted
mockOne.add("one");
verify(mockOne).add("one");
// 验证没有调用过某个行为
verify(mockOne, never()).add("two");
// 验证两个mock之间没有发生交互
verifyZeroInteractions(mockTwo, mockThree);
}