Java测试-mockito学习
目录
- 1 Mockito
- 2 各种模拟使用
- 2.1 mock接口并验证
- 2.2 mock具体类,并进行stub
- 2.3 参数匹配器-Argument matchers
- 2.4 验证实际调用的次数
- 2.5 stub 空返回值方法
- 2.6 按顺序验证行为
- 2.7 冗余的mock对象验证
- 2.8 迭代器风格的stub
- 2.9 支持回调的stub
- 2. 10 spy真实对象
- 2-11 部分真实mock
- 2-12 重置mock
- 2-13 @Mock和@InjectMocks
- 2-14 行为驱动开发模式BDD
- 参考文献
1 Mockito
mockito是Java中用于单元测试的模拟框架,Mockito库支持模拟创建、验证和存根。
通常和Junit框架组合完成对项目的单元测试。
2 各种模拟使用
2.1 mock接口并验证
测试demo-1:
//1--mock一些接口, 使用verify验证某些行为是否发生仅过一次@Testvoid mockListTest() {List listMock = mock(List.class);listMock.add("one");listMock.get(1);listMock.clear();verify(listMock).add("one");verify(listMock).clear();verify(listMock).get(1);}
mock
接口,并可verify
行为是否发生过和已经发生次数。
2.2 mock具体类,并进行stub
测试demo-2:
//2--mock一些具体的类,并进行stub@Testvoid mockConcreteList() {LinkedList mockLinkedList = mock(LinkedList.class);when(mockLinkedList.get(0)).thenReturn("first");when(mockLinkedList.get(1)).thenThrow(new RuntimeException());System.out.println(mockLinkedList.get(0));
// System.out.println(mockLinkedList.get(1));System.out.println(mockLinkedList.get(999));}
mock
具体类,stub
具体的行为返回值。
2.3 参数匹配器-Argument matchers
测试demo-3:
@Testvoid mockArgumentMatcherTest() {LinkedList mockLinkedList = mock(LinkedList.class);when(mockLinkedList.get(anyInt())).thenReturn("element");System.out.println(mockLinkedList.get(Integer.MAX_VALUE));//可以传入lambda表达式when(mockLinkedList.contains(argThat((str) -> {String strNew = (String) str;return strNew.length() > 5;}))).thenReturn(true);System.out.println(mockLinkedList.contains("cece"));System.out.println(mockLinkedList.contains("cecece"));verify(mockLinkedList).get(anyInt());}
运行结果:
可以使用内建的anyInt
……系列或者自定义argThat
,来完成stub需求,支持lambda表达式。
2.4 验证实际调用的次数
测试demo-4:
@Testvoid verifyExactNumberTest() {LinkedList mockLinkedList = mock(LinkedList.class);mockLinkedList.add("one");mockLinkedList.add("two");mockLinkedList.add("two");mockLinkedList.add("three");mockLinkedList.add("three");mockLinkedList.add("three");//默认一次verify(mockLinkedList).add("one");verify(mockLinkedList, times(1)).add("one");//验证两次、三次verify(mockLinkedList, times(2)).add("two");verify(mockLinkedList, times(3)).add("three");//验证从未添加的元素verify(mockLinkedList, never()).add("never add");//验证atLeast、atMostverify(mockLinkedList, atLeast(1)).add("three");verify(mockLinkedList, atMost(1)).add("one");}
可以使用支持的times、never、atLeast和atMost
进行调用次数验证。
2.5 stub 空返回值方法
测试demo-5:
@Testvoid stubVoidTest() {LinkedList mockLinkedList = mock(LinkedList.class);doThrow(new RuntimeException()).when(mockLinkedList).clear();//调用clear方法,返回异常mockLinkedList.clear();}
执行结果:
mock
返回值为void
方法。
2.6 按顺序验证行为
测试demo-6:
@Testvoid verifyInOrderTest() {List singleList = mock(List.class);singleList.add("was add first");singleList.add("was add second");//单一mock验证顺序InOrder singleInOrder = inOrder(singleList);singleInOrder.verify(singleList).add("was add first");singleInOrder.verify(singleList).add("was add second");List firstMock = mock(List.class);List secondMock = mock(List.class);firstMock.add("one");firstMock.add("two");secondMock.add("one");secondMock.add("two");InOrder order = inOrder(firstMock, secondMock);//多个mock验证添加顺序order.verify(firstMock).add("two");order.verify(secondMock).add("one");order.verify(secondMock).add("two");}
通过InOrder
进行行为顺序验证,支持多个mock
对象的顺序验证。
2.7 冗余的mock对象验证
测试demo-7:
@Testvoid redundantInvocationTest() {List mockList = mock(List.class);mockList.add("one");mockList.add("two");//这个没有验证mockList.add("three");verify(mockList).add("two");verify(mockList).add("one");verifyNoMoreInteractions(mockList);}
执行结果:
verifyNoMoreInteractions
支持验证多余的交互行为(交互了但没有verify
)。
2.8 迭代器风格的stub
测试demo-8:
@Testvoid stubIteratorTest() {List mockList = mock(List.class);when(mockList.get(1)).thenReturn("foo", "test");//按顺序返回System.out.println(mockList.get(1));System.out.println(mockList.get(1));//之后都是最后一个迭代test获胜System.out.println(mockList.get(1));}
执行结果:
可以返回多个值,每次调用都会向后迭代,超过长度会重复最后一个stub
的结果。
2.9 支持回调的stub
测试demo-9:
@Testvoid stubWithCallbackTest() {List<String> mockList = mock(List.class);//使用thenAnswer传入回调when(mockList.get(anyInt())).thenAnswer(invocation -> {Object[] arguments = invocation.getArguments();Object mock = invocation.getMock();return "called with arguments: " + Arrays.toString(arguments);});System.out.println(mockList.get(111));}
运行结果:
支持通过thenAnswer
传入lambda表达式,自定义回调函数处理返回结果。
2. 10 spy真实对象
测试demo-10:
@Testvoid spyRealObjectTest() {LinkedList<String> linkedList = new LinkedList<>();LinkedList<String> spy = spy(linkedList);spy.add("one");spy.add("two");System.out.println(spy.get(0));System.out.println(spy.get(1));//进行stubwhen(spy.size()).thenReturn(100);System.out.println(spy.size());verify(spy).add("one");List list = new LinkedList();List spy1 = spy(list);}
运行结果:
当spy
真实对象,将会调用对象的真实方法,同时可以支持stub
对象行为,但是有局限性,比如下面情况:
//Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)when(spy1.get(0)).thenReturn("foo");//You have to use doReturn() for stubbingdoReturn("foo").when(spy).get(0);
运行结果:
因为使用when,spy.get(0)
将被调用,而此时还没有元素,会抛出异常。而doReturn
没有调用方法,只是设置了返回值。
2-11 部分真实mock
测试demo-11:
@Testvoid realPartMockTest() {CalculatorMapper mock = mock(CalculatorMapper.class);//调用selectFirst调用真实方法when(mock.selectFirst(anyInt())).thenCallRealMethod();Assertions.assertEquals(101, mock.selectFirst(1));}
thenCallRealMethod
支持调用真实对象方法。
2-12 重置mock
测试demo-12:
@Testvoid resetMockTest() {List mock = mock(List.class);when(mock.size()).thenReturn(10);mock.add(1);//reset所有发生的调用和行为reset(mock);verifyNoMoreInteractions(mock);}
一般我们测试都是针对单独的一个功能,没有必要进行重置。
2-13 @Mock和@InjectMocks
测试demo-13:
@ExtendWith(MockitoExtension.class)
public class CalculatorManagerTest {//注入mock,会对注入的属性根据测试类中定义的mock类进行注入。@InjectMocksprivate CalculatorService calculatorService;//mock其它类,需要对方法返回值进行mock设置@Mock private CalculatorMapper calculatorMapper;@BeforeEachvoid setUp() {}@Testpublic void calculatorManagerTest() {when(calculatorMapper.selectFirst(anyInt())).thenReturn(100);when(calculatorMapper.selectSecond(anyInt())).thenReturn(100);Assertions.assertEquals(200, calculatorService.add(1, 1));}
}
可以使用注解@Mock
更简单的mock
一个对象,如果对象中有注入对象,可以使用@InjectMocks
进行mock
对象注入。
2-14 行为驱动开发模式BDD
BDD
一般定义为下:
- 给定
given
:场景开头的初始上下文,一个或多个子句. - 时间
when
:触发场景的事件. - 然后
then
:在一个或多个条款中的预期结果。
测试demo-14:
@Testvoid bddMockTest() {List mockList = mock(List.class);//given,列表获取常见given(mockList.get(anyInt())).willReturn(100, 200, 300);//when,第一次获取mockList.get(0);//then,判断获取第二次结果Assertions.assertEquals(mockList.get(0), 200);//verify行为的bdd模式then(mockList).should(times(2)).get(0);}
mockito工作组建议使用的编写测试模式。
库中已经封装了对于的BDD
调用方式。
参考文献
[1] Mockito文档.
Java测试-mockito学习相关推荐
- TurtleSoup Java测试学习项目
TurtleSoup Java测试学习项目 项目文件下载: Java测试学习项目 前言 实习题目给的是全英文的,由于整个描述也比较长,前言这里做一个简述概括,整个实习2主要是教我们如何通过测试用例进行 ...
- 2021年,Java开发者值得学习的13项技能
本文分享自百度开发者中心2021年,Java开发者值得学习的13项技能 作者 | Olivia Cuthbert 译者 | 王强 策划 | 刘燕 如果你想在这个竞争激烈的世界里,成为一名熟练开发 Ja ...
- 2021 年,Java 开发者值得学习的 13 项技能
作者 | Olivia Cuthbert 译者 | 王强 策划 | 刘燕 如果你想在这个竞争激烈的世界里,成为一名熟练开发 Java 项目的开发人员,你应该学习很多东西才行.你需要掌握许多技能,具体应 ...
- java测试步骤_java测试框架的方法
项目开发过程中使用的单元测试框架有Junit.TestNG以及Mockito,Junit和TestNG使用的比较多,Mockito最近才开始使用. TestNG与JUnit的相同点 1. 使用anno ...
- java测试有哪些_java测试有哪些欢迎来电
java测试有哪些欢迎来电,5.学员毕业后,仍可随时回来,免费技术提升,一次交费,永久学习. java测试有哪些欢迎来电, 单元测试的不神器,提高运行速度,跟真实环境解耦.jacoco:java 的代 ...
- Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论
Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论 创建用户自定义的类加载器 要创建用户自定义的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的f ...
- [转]java.lang.instrument 学习(一)
[转]java.lang.instrument 学习(一) 收藏 sunyh 发表于 10个月前 阅读 40 收藏 3 点赞 1 评论 0 转自:http://jiangbo.me/blog/201 ...
- Java IO流学习总结七:Commons IO 2.5-FileUtils
Java IO流学习总结七:Commons IO 2.5-FileUtils 转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/5497 ...
- Java IO流学习总结六:ByteArrayInputStream、ByteArrayOutputStream
Java IO流学习总结六:ByteArrayInputStream.ByteArrayOutputStream 转载请标明出处:http://blog.csdn.net/zhaoyanjun6/ar ...
最新文章
- 25 iOS performance TipsTricks 笔记
- 一个4体低位交叉的存储器_GD25Q16CSIG|NRAM存储器的原理及优势是什么?
- [刷题]算法竞赛入门经典(第2版) 4-3/UVa220 - Othello
- Hadoop从安装Linux到搭建集群环境
- 关于Java中 求Logn/log2 的精度问题。
- Hibernate开发和对象状态
- eclipse web项目中css无法显示
- 游戏大魔王少不了王者荣耀壁纸图片
- Rust : wasm尝试 与wasmtime库
- esxi 环境 西数硬盘测试软件,总算基本完美的折腾好ESXI+群晖+NVME
- 千方百剂医药管理系统对接第三方WMS系统(天力士物流)
- python调用百度地图,通过经纬度定位
- idea maven添加子moudle父pom被覆盖
- 云原生数据湖以存储、计算、数据管理等能力通过信通院评测认证
- 淘宝近12亿条用户信息泄露,犯罪分子获利34万
- SpringBoot+MongoDB GridFS文件上传、下载、预览实战
- 【Python网络编程和并发-多线程共享数据混乱引出同步锁】
- 高速电路设计基本概念之——近端串扰和远端串扰
- JS生成 GUID 或 UUID 四种方法
- Android仿英雄联盟/斗鱼波形加载动画