使用Mockito进行单元测试【1】——mock and verify[转]
本文转自:http://qiuguo0205.iteye.com/blog/1443344
1. 为什么使用Mockito来进行单元测试?
回答这个问题需要回答两个方面,第一个是为什么使用mock?mock其实是一种工具的简称,他最大的功能是帮你把单元测试的耦合分解开,如果你的代码对另一个类或者接口有依赖,它能够帮你模拟这些依赖,并帮你验证所调用的依赖的行为。
比如一段代码有这样的依赖:

当我们需要测试A类的时候,如果没有mock,则我们需要把整个依赖树都构建出来,而使用mock的话就可以将结构分解开,像下面这样:

还有一个问题是mock工具那么多,为什么我们要用mockito呢?原因很简单:他非常好用!
他使用执行后验证的模型,语法更简洁并且更加贴近程序员的思考方式,能够模拟类而不仅仅是接口等等。总之如果你想使用mock的话,试用mockito,你不会后悔的:)
引用的图摘自http://www.theserverside.com/news/1365050/Using-JMock-in-Test-Driven-Development,那里对mock的使用有很好的介绍。
http://www.sizovpoint.com/2009/03/java-mock-frameworks-comparison.html是一篇非常好的mock工具比较的文章,我就是从它认识的mockito,他也有对mock使用的精彩介绍。
还有一篇文章总结了mockito的好处:http://java.dzone.com/articles/mockito-pros-cons-and-best
当然,要想真正了解mockito的好处,就必须写写代码练习一下了。
2. Mockito使用实例
这里的代码基本都是从http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html
摘出来的,然后加上了自己的一些学习验证,这个网页挺重要的,会多次提到,以后就简称”网页“了。让我们通过这些实例来看看mockito的强大功能吧:
1. 让我们验证一些行为吧
- //Let's import Mockito statically so that the code looks clearer
- import static org.mockito.Mockito.*;
- //mock creation
- List mockedList = mock(List.class);
- // using mock object
- mockedList.add("one");
- mockedList.clear();
- mockedList.add("3"); // no verify? OK
- // verification
- verify(mockedList).add("one");
- verify(mockedList).clear();
- // verify(mockedList).add("2"); // this will throw an exception
首先通过这段代码介绍什么是mock:首先使用Mockito的静态方法mock,我们就可以创建一个类的mock实例,这个mock实例拥有这个List的所有方法接口,并且给这些方法以最基本的实现:如果是返回void,他什么都不做,否则他就返回null或0等基本类型的值。比如中间的三句调用了mock的方法,即使将来不验证也没有任何关系。
在验证阶段,当我们验证这个mock的方法add("one")是否被调用的时候,他不会抛出异常,因为我们确实调用了这个方法,但是当我们验证它是否调用add("2")的时候,就会抛出异常,说明我们没有调用过这个方法,此时的测试就会失败。
所以验证的意思是”查看我们到底有没有调用过mock的这个方法“。
2. 它能提供桩[stub]测试吗?
相信这样的场景我们都遇到过,有一个方法的输入是一个List,在这个方法中我们遍历这个List,读取数据,做相应的操作。往常我们可能需要自己创建一个ArrayList,并且将需要的测试的参数add进list中,这样就可以分别进行测试了。下面看看使用mockito是怎么做到的:
- // You can mock concrete classes, not only interfaces
- LinkedList mockedList = mock(LinkedList.class);
- // stubbing
- 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));
- // following prints "null" because get(999) was not stubbed
- System.out.println(mockedList.get(999));
- // Although it is possible to verify a stubbed invocation, usually it's just redundant
- // See http://monkeyisland.pl/2008/04/26/asking-and-telling
- verify(mockedList, atLeast(2)).get(0);
首先我们可以看到mockito是可以mock类而不仅仅是接口的,而stub的语法也非常接近人的阅读习惯:when(mockedList.get(0)).thenReturn("first"); 当调用get(0)的时候返回"first"。
这里需要注意以下几点:
【1】mock实例默认的会给所有的方法添加基本实现:返回null或空集合,或者0等基本类型的值。
【2】当我们连续两次为同一个方法使用stub的时候,他只会只用最新的一次。
【3】一旦这个方法被stub了,就会一直返回这个stub的值。
像下面这段代码,你猜会打印什么?
- when(mockedList.get(0)).thenReturn("first");
- when(mockedList.get(0)).thenReturn("oops");
- System.out.println(mockedList.get(0));
- System.out.println(mockedList.get(0));
3. 参数匹配
下面我们看看mockito强大的参数匹配机制,当mockito执行verify的时候,它实际上对参数执行的是自然地java方式——equals方法。有事我们需要对参数进行灵活匹配的时候就可以用到”参数匹配器“【argument matchers】了
- // stubbing using built-in anyInt() argument matcher
- when(mockedList.get(anyInt())).thenReturn("element");
- // following prints "element"
- System.out.println(mockedList.get(999));
- // you can also verify using an argument matcher
- verify(mockedList).get(anyInt());
这里的anyInt是mockito内建的众多方法之一,其他可以参考mockito主页上的信息,你也可以调用hamcrest的matchers。
警告:若方法中的某一个参数使用了matcher,则所有的参数都必须使用matcher:
- // correct
- verify(mock).someMethod(anyInt(), anyString(), eq("third argument"));
- // will throw exception
- verify(mock).someMethod(anyInt(), anyString(), "third argument");
4. 继续讨论Verification
前面的例子都是和网页上的例子一一对应的,现在我们集中讨论一下mockito在verify上提供的强大功能,大部分例子都很简单,所以我基本就是简单的罗列:
# 验证方法被调用的次数 网页例子4
- //using mock
- 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");
- //verification using atLeast()/atMost()
- verify(mockedList, atLeastOnce()).add("three times");
- verify(mockedList, atLeast(2)).add("five times");
- verify(mockedList, atMost(5)).add("three times");
# 按顺序验证 网页例子6
- // 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);
- //following will make sure that add is first called with "was added first, then with "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
- 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 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");
- // Oh, and A + B can be mixed together at will
# 确保某些方法没有被调用 网页例子7
- //using mocks - only mockOne is interacted
- mockOne.add("one");
- //ordinary verification
- verify(mockOne).add("one");
- //verify that method was never called on a mock
- verify(mockOne, never()).add("two");
- //verify that other mocks were not interacted
- verifyZeroInteractions(mockTwo, mockThree);
# 从前面的例子我们可以看到,能够很容易地找到冗余的调用 网页例子8
- //using mocks
- mockedList.add("one");
- mockedList.add("two");
- verify(mockedList).add("one");
- //following verification will fail
- verifyNoMoreInteractions(mockedList);
OK,看过Mockito的 mock 和 verify的能力,你可能已经喜欢上Mockito了,不过这只是Mockito强大功能的一部分,下一篇接着翻译我个人用的最多的stub的功能,真的不可错过,看完之后你绝对能够惊叹Mockito的实力的;-)
使用Mockito进行单元测试【1】——mock and verify[转]的更多相关文章
- Java单元测试(Junit+Mock+代码覆盖率)---------转
Java单元测试(Junit+Mock+代码覆盖率) 原文见此处 单元测试是编写测试代码,用来检测特定的.明确的.细颗粒的功能.单元测试并不一定保证程序功能是正确的,更不保证整体业务是准备的. 单元测 ...
- 基于Springboot+Junit+Mockito做单元测试
前言 前面的两篇文章讨论过< 为什么要写单元测试,何时写,写多细 >和<单元测试规范>,这篇文章介绍如何使用Springboot+Junit+Mockito做单元测试,案例选取 ...
- Spring Boot单元测试(Mock)
Spring Boot单元测试(Mock) Java个人学习心得 2017-08-12 16:07 Mock 单元测试的重要性就不多说了,我这边的工程一般都是Spring Boot+Mybatis(详 ...
- Spring Boot 2 实践记录之 使用 Powermock、Mockito 对 UUID 进行 mock 单元测试
由于注册时,需要对输入的密码进行加密,使用到了 UUID.sha1.md 等算法.在单元测试时,使用到了 Powermock,记录如下. 先看下加密算法: import org.apache.comm ...
- 使用Mockito进行单元测试【2】—— stub 和 高级特性[转]
一篇中介绍了Mockito的基本信息,现在接着介绍Mockito强大的stub功能 2. Mockito使用实例 5. 对连续的调用进行不同的返回 (iterator-style stubbing) ...
- Java单元测试(Junit+Mock+代码覆盖率)
微信公众号[程序员江湖] 作者黄小斜,斜杠青年,某985硕士,阿里 Java 研发工程师,于 2018 年秋招拿到 BAT 头条.网易.滴滴等 8 个大厂 offer,目前致力于分享这几年的学习经验. ...
- 使用 Junit + Mockito 实践单元测试
一.前言 相信做过开发的同学,都多多少少写过下面的代码,很长一段时间我一直以为这就是单元测试... @SpringBootTest @RunWith(SpringRunner.class) publi ...
- Mockito+Junit5单元测试
参考: https://segmentfault.com/a/1190000006746409 https://waylau.com/mockito-quick-start/ 1.引入依赖 下面这个最 ...
- Mockito单测,mock service层的mapper
转载:https://blog.csdn.net/paincupid/article/details/53561435 1.引入mockito jar包 <dependency> < ...
随机推荐
- Directx11学习笔记【二十】 使用DirectX Tool Kit加载mesh
本文由zhangbaochong原创,转载请注明出处:http://www.cnblogs.com/zhangbaochong/p/5788482.html 现在directx已经不再支持.x文件了, ...
- C# 5.0 Async函数的提示和技巧
一.创建Async函数 Async是C# 5.0中新增的关键字,通过语法糖的形式简化异步编程,它有如下三种方式: async Task<T> MyReturningMethod { ret ...
- Spring Assert主张 (参议院检测工具的方法-主张)
Web 收到申请表格提交的数据后都需要对其进行合法性检查,假设表单数据是不合法的,该请求将被拒绝.分类似的,当我们写的类方法,该方法还经常需要组合成参 法国检查.假设参议院不符合要求,方法通过抛出异常 ...
- (五岁以下儿童)NS3样本演示:桥模块演示样品csma-bridge.cc凝视程序
(五岁以下儿童)NS3:桥模块演示样品csma-bridge.cc凝视程序 1.Ns3 bridge模csma-bridge.cc演示示例程序的目光 // Network topology // // ...
- Principle使用教程
本次分享主要有以下几点内容: 1.初识界面2.两个关键操作3.案例一:滑动4.案例二:点击跳转 5.案例三:跟随动画(抽屉效果) 1初识界面Principle的界面与Sketch基本一致,如下图: a ...
- Windows 驱动发展基金会(九)内核函数
Windows 驱动发展基金会系列,转载请注明出处:http://blog.csdn.net/ikerpeng/article/details/38849861 这里主要介绍3类Windows的内核函 ...
- poj2112 Optimal Milking --- 最大流量,二分法
nx一个挤奶器,ny奶牛,每个挤奶罐为最m奶牛使用. 现在给nx+ny在矩阵之间的距离.要求使所有奶牛挤奶到挤奶正在旅程,最小的个体奶牛步行距离的最大值. 始感觉这个类似二分图匹配,不同之处在于挤奶器 ...
- 【Andrioid】在Gradle编译时生成一个不同的版本号,动态设置应用程序标题,应用程序图标,更换常数
写项目的时候常常会遇到下面的情况: 1.须要生成測试版本号和正式版本号的apk 2.測试版本号和正式版本号的URL是不一样的 3.測试版本号和正式版本号的包名须要不一致,这样才干安装到同一部手机上面. ...
- Oracle FGA审计记录的清理步骤
注意:本文为原创文章,转载请注明出处: http://blog.csdn.net/msdnchina/article/details/38435999 一.确认有哪些fga审计策略, 从select ...
- Android开发学习总结(六)—— APK反编译(转)
学习和开发Android应用有一段时间了,今天写一篇博客总结一下Android的apk文件反编译.我们知道,Android应用开发完成之后,我们最终都会将应用打包成一个apk文件,然后让用户通过手机或 ...