Mockito使用指南
来源:互联网 发布:kuka机器人基本编程 编辑:程序博客网 时间:2024/06/06 13:03
版权声明:本文为博主原创文章,转载请标明出处,谢谢
目录(?)[+]
转载请标明出处:http://blog.csdn.net/shensky711/article/details/52771493
本文出自: 【HansChen的博客】
- mock和Mockito的关系
- Mockito使用举例
- Android Studio工程配置Mockito
- Mockito使用方法
- 验证行为
- Stubbing
- 参数匹配
- 验证准确的调用次数最多最少从未等
- 为void方法抛异常
- 验证调用顺序
- 验证mock对象没有产生过交互
- 查找是否有未验证的交互
- Mock注解
- 根据调用顺序设置不同的stubbing
- doReturndoThrow doAnswerdoNothingdoCallRealMethod等用法
- spy监视真正的对象
- 为未stub的方法设置默认返回值
- 参数捕捉
- 真正的部分模拟TODO尚未搞清楚啥意思
- 重置mocks
- Serializable mocks
- 更多的注解Captor Spy InjectMocks
- 超时验证
- 查看是否mock或者spy
mock和Mockito的关系
在软件开发中提及”mock”,通常理解为模拟对象。
为什么需要模拟? 在我们一开始学编程时,我们所写的对象通常都是独立的,并不依赖其他的类,也不会操作别的类。但实际上,软件中是充满依赖关系的,比如我们会基于service类写操作类,而service类又是基于数据访问类(DAO)的,依次下去,形成复杂的依赖关系。
单元测试的思路就是我们想在不涉及依赖关系的情况下测试代码。这种测试可以让你无视代码的依赖关系去测试代码的有效性。核心思想就是如果代码按设计正常工作,并且依赖关系也正常,那么他们应该会同时工作正常。
有些时候,我们代码所需要的依赖可能尚未开发完成,甚至还不存在,那如何让我们的开发进行下去呢?使用mock可以让开发进行下去,mock技术的目的和作用就是模拟一些在应用中不容易构造或者比较复杂的对象,从而把测试与测试边界以外的对象隔离开。
我们可以自己编写自定义的Mock对象实现mock技术,但是编写自定义的Mock对象需要额外的编码工作,同时也可能引入错误。现在实现mock技术的优秀开源框架有很多,Mockito就是一个优秀的用于单元测试的mock框架。Mockito已经在github上开源,详细请点击:https://github.com/mockito/mockito
除了Mockito以外,还有一些类似的框架,比如:
- EasyMock:早期比较流行的MocK测试框架。它提供对接口的模拟,能够通过录制、回放、检查三步来完成大体的测试过程,可以验证方法的调用种类、次数、顺序,可以令 Mock 对象返回指定的值或抛出指定异常
- PowerMock:这个工具是在EasyMock和Mockito上扩展出来的,目的是为了解决EasyMock和Mockito不能解决的问题,比如对static, final, private方法均不能mock。其实测试架构设计良好的代码,一般并不需要这些功能,但如果是在已有项目上增加单元测试,老代码有问题且不能改时,就不得不使用这些功能了
- JMockit:JMockit 是一个轻量级的mock框架是用以帮助开发人员编写测试程序的一组工具和API,该项目完全基于 Java 5 SE 的 java.lang.instrument 包开发,内部使用 ASM 库来修改Java的Bytecode
Mockito已经被广泛应用,所以这里重点介绍Mockito。
Mockito使用举例
这里我们直接通过一个代码来说明mockito对单元测试的帮助,代码有三个类,分别如下:
Person类:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
PersonDAO:
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
PersonService:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
在这里,我们要进行测试的是PersonService类的update方法,我们发现,update方法依赖PersonDAO,在开发过程中,PersonDAO很可能尚未开发完成,所以我们测试PersonService的时候,所以该怎么测试update方法呢?连接口都还没实现,怎么知道返回的是true还是false?在这里,我们可以这样认为,单元测试的思路就是我们想在不涉及依赖关系的情况下测试代码。这种测试可以让你无视代码的依赖关系去测试代码的有效性。核心思想就是如果代码按设计正常工作,并且依赖关系也正常,那么他们应该会同时工作正常。所以我们的做法是mock一个PersonDAO对象,至于实际环境中,PersonDAO行为是否能按照预期执行,比如update是否能成功,查询是否返回正确的数据,就跟PersonService没关系了。PersonService的单元测试只测试自己的逻辑是否有问题
下面编写测试代码:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
我们对PersonDAO进行mock,并且设置stubbing,stubbing设置如下:
- 当getPerson方法传入1的时候,返回一个Person对象,否则默认返回空
- 当调update方法的时候,返回true
我们验证了两种情况:
- 更新id为1的Person的名字,预期:能在DAO中找到Person并更新成功
- 更新id为2的Person的名字,预期:不能在DAO中找到Person,更新失败
这样,根据PersonService的update方法的逻辑,通过这两个test case之后,我们认为代码是没有问题的。mockito在这里扮演了一个为我们模拟DAO对象,并且帮助我们验证行为(比如验证是否调用了getPerson方法及update方法)的角色
Android Studio工程配置Mockito
Android Studio中使用Mockito非常简单,只需要在build.gradle文件中加入依赖即可。如图:
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
Mockito使用方法
Mockito的使用,有详细的api文档,具体可以查看:http://site.mockito.org/mockito/docs/current/org/mockito/Mockito.html,下面是整理的一些常用的使用方式。
验证行为
一旦创建,mock会记录所有交互,你可以验证所有你想要验证的东西
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
Stubbing
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
对于stubbing,有以下几点需要注意:
- 对于有返回值的方法,mock会默认返回null、空集合、默认值。比如,为int/Integer返回0,为boolean/Boolean返回false
- stubbing可以被覆盖,但是请注意覆盖已有的stubbing有可能不是很好
- 一旦stubbing,不管调用多少次,方法都会永远返回stubbing的值
- 当你对同一个方法进行多次stubbing,最后一次stubbing是最重要的
参数匹配
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
如果你使用了参数匹配器,那么所有参数都应该使用参数匹配器
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
验证准确的调用次数,最多、最少、从未等
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
为void方法抛异常
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
验证调用顺序
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
验证mock对象没有产生过交互
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
查找是否有未验证的交互
不建议过多使用,api原文:A word of warning: Some users who did a lot of classic, expect-run-verify mocking tend to use verifyNoMoreInteractions() very often, even in every test method. verifyNoMoreInteractions() is not recommended to use in every test method. verifyNoMoreInteractions() is a handy assertion from the interaction testing toolkit. Use it only when it’s relevant. Abusing it leads to overspecified, less maintainable tests.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
@Mock注解
- 减少代码
- 增强可读性
- 让verify出错信息更易读,因为变量名可用来描述标记mock对象
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
根据调用顺序设置不同的stubbing
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
doReturn()|doThrow()| doAnswer()|doNothing()|doCallRealMethod()等用法
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
spy监视真正的对象
- spy是创建一个拷贝,如果你保留原始的list,并用它来进行操作,那么spy并不能检测到其交互
- spy一个真正的对象+试图stub一个final方法,这样是会有问题的
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
为未stub的方法设置默认返回值
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
参数捕捉
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
真正的部分模拟(TODO:尚未搞清楚啥意思。。。)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
重置mocks
Don’t harm yourself. reset() in the middle of the test method is a code smell (you’re probably testing too much).
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
Serializable mocks
WARNING: This should be rarely used in unit testing.
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
更多的注解:@Captor, @Spy, @InjectMocks
- @Captor 创建ArgumentCaptor
- @Spy 可以代替spy(Object).
- @InjectMocks 如果此注解声明的变量需要用到mock对象,mockito会自动注入mock或spy成员
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
超时验证
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
查看是否mock或者spy
- Mockito使用指南
- Mockito使用指南
- Mockito
- mockito
- Mockito
- Mockito
- mockito
- Mockito
- Mockito
- Mockito
- Mockito
- Mockito
- Mockito
- Mockito实例-Junit & Mockito
- Mockito入门
- Mockito入门
- Mockito框架
- Mockito使用
- 新的一天开始了
- getLocationOnScreen; View.getLocationInWindow(int[] location)
- OpenCV学习笔记(4)——mixChannels函数
- CC2530 zigbee 全信道扫描
- Css3变换和过渡
- Mockito使用指南
- Intellij IDEA基本配置
- hdu 6085 bitset优化
- sqlserver中like模糊查询如何区分大小写
- js中 ||的意思,js中 o = o || {};是什么意思呢?
- webpack-vue全家桶之实现border-1px
- AndroidStudio或Eclipse中导出应用程序数据库
- HDU1394 线段树 单点更新 求逆序数
- 14.1-全栈Java笔记: Java语言中GUI到底是神马鬼?| AWT | Swing