什么是 Mock 测试

Mock测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法。什么是不容易构造的对象呢?例如HttpServletRequest,需要在有servlet容器环境中创建获取。那不容易获取的对象呢?如一个JedisCluster,需要准备redis相关环境,然后设置进去等等。

Mock 可以分解在单元测试中耦合的其他类或者接口,它能够帮你模拟这些依赖,并帮你验证所调用的依赖的行为。

场景事例

当我们需要测试OrderService时,按照我们常规的做法呢,都是要先准备好redis,跟db的环境,然后构造UserService跟CouponService注入进来,此时需要构建完整的依赖树,其过程是比较繁琐的,万一数据库连不上,依赖找不到,服务挂了... 时间一长可能会打击我们对项目进行单测的积极性,所以这时候很有必要寻求一种优雅的方式来解决。

铛铛铛~这时候Mockito出现了(java中Mock框架比较多,但是本篇只介绍这个),它会把那些繁琐的依赖统统转化为Mock Object,如下图,这样我们就可以专注的进行我们的单测,减少在解决依赖上浪费的时间了。

直接开干

关于Mockito的简介这里就不在赘述了,大家有兴趣可以自行去官方文档查阅,这里主要带大家了解一些常用的Mock方法。

maven依赖

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.23.4</version>
<scope>test</scope>
</dependency>

  

为了代码测试的方便,直接在测试类中静态导入 import static org.mockito.Mockito.*;

基础方法

@Test
public void testMockBase(){
//创建ArrayList的Mock对象
List mockList = mock(ArrayList.class);
//pass
Assert.assertTrue(mockList instanceof ArrayList); //当我们mockList调用方法去add("张三")的时候会返回true
when(mockList.add("张三")).thenReturn(true);
//当我们mockList调用方法size()的时候返回10
when(mockList.size()).thenReturn(10);
//pass
Assert.assertTrue(mockList.add("张三"));
//pass
Assert.assertFalse(mockList.add("李四"));
//pass
Assert.assertEquals(mockList.size(),10);
//null
System.out.println(mockList.get(0));
}
 

mock静态方法会创建一个Mock对象,由于 Mock对象 并不会真的执行方法中的代码,所以如果未指定返回值的话会返回默认值(如19行)。第九、十行我们指定了mockList在执行特定方法后需要返回的值,所以在assertTrue校验是没问题的,但是add("李四"),我们并没设置,所以是false。

校验方法调用次数

//使用mock
List mockedList = mock(ArrayList.class);
mockedList.add("once"); mockedList.add("twice");
mockedList.add("twice"); mockedList.add("three times");
mockedList.add("three times");
mockedList.add("three times"); //这里默认是判断该方法调用times(1),同下
verify(mockedList).add("once");
verify(mockedList, times(1)).add("once"); verify(mockedList, times(2)).add("twice");
verify(mockedList, times(3)).add("three times");
//从没调用,times(0)
verify(mockedList, never()).add("never happened");
//最少一次,最少几次,最多几次
verify(mockedList, atLeastOnce()).add("three times");
verify(mockedList, atLeast(2)).add("three times");
verify(mockedList, atMost(5)).add("three times");
 

其实在上述的代码中,命名是比较直观的,所以我这边就直接注释在代码中了。

校验方法调用时长

//方法执行在100ms以内的时候可以通过
verify(mock, timeout(100)).someMethod();
//同上
verify(mock, timeout(100).times(1)).someMethod(); //方法2次调用均没超过100ms
verify(mock, timeout(100).times(2)).someMethod(); verify(mock, timeout(100).atLeast(2)).someMethod();
 

通过超时检测可以校验我们的方法逻辑会不会有出现问题而导致超时的地方。

参数匹配

linkedList.add("element");
// anyInt() 任何整数我们都返回 element
when(linkedList.get(anyInt())).thenReturn("element"); System.out.print(linkedList.get(10));//返回element

方法抛出异常

 @Test(expected = RuntimeException.class)
public void doThrow(){
List list = mock(List.class);
doThrow(new RuntimeException()).when(list).add(1);
list.add(1);
}

使用注解注入

  public class ArticleManagerTest {

       @Mock private ArticleCalculator calculator;
@Mock private ArticleDatabase database;
@Mock private UserProvider userProvider; private ArticleManager manager;
 

要注意的是,通过注解的方式用使用的话,我们必须在添加初始化mock的代码,不然即使标注了注解也会是null

MockitoAnnotations.initMocks(testClass);

关于Mockito更多详细的用法,大家可以直接参考官方文档,因为各种“奇技淫巧”确实比较多,后面也更新对java8 lambda的支持,很多功能还是期待大家去挖掘~

更多详细用法可直接参考官方文档:

static.javadoc.io/org.mockito…

相信当你熟练使用Mockito以后,你会爱上写单测的,也会让你代码健壮性有所加强。有些bug能提前发现的话,总比运行的时候被别人半夜叫起来修复舒服是吧?

微信公众号《深夜里的程序猿》 -  每天分享最干的干货

Java单元测试神器之Mockito的更多相关文章

  1. Java单元测试(Junit+Mock+代码覆盖率)

    微信公众号[程序员江湖] 作者黄小斜,斜杠青年,某985硕士,阿里 Java 研发工程师,于 2018 年秋招拿到 BAT 头条.网易.滴滴等 8 个大厂 offer,目前致力于分享这几年的学习经验. ...

  2. 原!!关于java 单元测试Junit4和Mock的一些总结

    最近项目有在写java代码的单元测试,然后在思考一个问题,为什么要写单元测试??单元测试写了有什么用??百度了一圈,如下: 软件质量最简单.最有效的保证: 是目标代码最清晰.最有效的文档: 可以优化目 ...

  3. java大神进阶之路

    既然励志在java路上走的更远,那就必须了解java的路径.先看图 更加细化的细节如下 一: 编程基础 不管是C还是C++,不管是Java还是PHP,想成为一名合格的程序员,基本的数据结构和算法基础还 ...

  4. Java单元测试(Junit+Mock+代码覆盖率)---------转

    Java单元测试(Junit+Mock+代码覆盖率) 原文见此处 单元测试是编写测试代码,用来检测特定的.明确的.细颗粒的功能.单元测试并不一定保证程序功能是正确的,更不保证整体业务是准备的. 单元测 ...

  5. Java Mocking入门—使用Mockito

    Java Mocking入门—使用Mockito 2014/03/10 | 分类: 基础技术 | 0 条评论 | 标签: 单元测试 分享到:8 本文由 ImportNew - liken 翻译自 dz ...

  6. [转帖]APP逆向神器之Frida【Android初级篇】

    APP逆向神器之Frida[Android初级篇] https://juejin.im/post/5d25a543e51d455d6d5358ab 说到逆向APP,很多人首先想到的都是反编译,但是单看 ...

  7. ORACLE恢复神器之ODU/AUL/DUL

    分享ORACLE数据库恢复神器之ODU.DUL和AUL工具. ODU:ORACLE DATABASE UNLOADER DUL:DATA UNLOADER AUL:也称MyDUL 关于三种工具说明: ...

  8. Java单元测试技术1

    另外两篇关于介绍easemock的文章:EasyMock 使用方法与原理剖析,使用 EasyMock 更轻松地进行测试 摘要:本文针对当前业软开发现状,先分析了WEB开发的技术特点和单元测试要解决的问 ...

  9. 转载-使用 Feed4JUnit 进行数据与代码分离的 Java 单元测试

    JUnit 是被广泛应用的 Java 单元测试框架,但是它没有很好的提供参数化测试的支持,很多测试人员不得不把测试数据写在程序里或者通过其它方法实现数据与代码的分离,在后续的修改和维护上有诸多限制和不 ...

随机推荐

  1. windows和centos下安装ActiveMQ

    版本:apache-activemq-5.10.2-bin.zip         (版本5.11+需要jdk7+) 官网: http://activemq.apache.org/download.h ...

  2. SpringCloud实战-Hystrix请求熔断与服务降级

    我们知道大量请求会阻塞在Tomcat服务器上,影响其它整个服务.在复杂的分布式架构的应用程序有很多的依赖,都会不可避免地在某些时候失败.高并发的依赖失败时如果没有隔离措施,当前应用服务就有被拖垮的风险 ...

  3. [CVPR 2017] Semantic Autoencoder for Zero-Shot Learning论文笔记

    http://openaccess.thecvf.com/content_cvpr_2017/papers/Kodirov_Semantic_Autoencoder_for_CVPR_2017_pap ...

  4. 语音识别中的CTC算法的基本原理解释

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文作者:罗冬日 目前主流的语音识别都大致分为特征提取,声学模型,语音模型几个部分.目前结合神经网络的端到端的声学模型训练方法主要CTC和基 ...

  5. Linux内核调试方法

    内核配置选项中要使能CONFIG_MAGIC_SYSRQ选项,这样系统启动之后,会生成/proc/sysrq-trigger节点用于调试. 其次,可以在/etc/sysctl.conf中设置kerne ...

  6. EasyUI集成Kindeditor使用

    在实际的项目中,我们需要在项目中集成富文本编辑器,而kindeditor作为一款优良的编辑器,在项目中或多或少都会用到! 实际效果图     使用方法: 1.首先下载Kindeditor编辑器,我这里 ...

  7. JAVA线程池shutdown和shutdownNow的区别

    一.区别介绍 shutDown()  当线程池调用该方法时,线程池的状态则立刻变成SHUTDOWN状态.此时,则不能再往线程池中添加任何任务,否则将会抛出RejectedExecutionExcept ...

  8. 解决MyEclipse注册失败的问题

    https://jingyan.baidu.com/article/acf728fd49519ff8e410a361.html

  9. 浅析mydumper

    Ⅰ.背景 mysqldump单线程备份,很慢 恢复慢,一张表一张表恢复, 如果备份了100G的数据,想恢复其中一个表,做不到(所有的表都在一个文件里) 所以推荐使用mydumper备份 备份并行,基于 ...

  10. 推荐《用Python进行自然语言处理》中文翻译-NLTK配套书

    NLTK配套书<用Python进行自然语言处理>(Natural Language Processing with Python)已经出版好几年了,但是国内一直没有翻译的中文版,虽然读英文 ...