什么是 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. python笔记:#007#变量

    变量的基本使用 程序就是用来处理数据的,而变量就是用来存储数据的 目标 变量定义 变量的类型 变量的命名 01. 变量定义 在 Python 中,每个变量 在使用前都必须赋值,变量 赋值以后 该变量 ...

  2. leetCode刷题(找到两个数组拼接后的中间数)

    There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two ...

  3. 15.linux基础

    1.目录 /:根目录,一般根目录下只存放目录,在Linux下有且只有一个根目录.所有的东西都是从这里开始.当你在终端里输入“/home”,你其实是在告诉电脑,先从/(根目录)开始,再进入到home目录 ...

  4. 从 源码 谈谈 redux compose

    compose,英文意思 组成,构成. 它的作用也是通过一系列的骚操作,实现任意的.多种的.不同的功能模块的组合,用来加强组件. 看看源码 https://github.com/reactjs/red ...

  5. 在Visual Studio中使用Debug Visualizers在C++中实现对原始类的自定义调试信息显示

    在Visual Studio中使用Debug Visualizers在C++中实现对原始类的自定义调试信息显示 当我们在VS的C++中使用vector.list.map等这些STL容器,在开启调试的时 ...

  6. OVMF基础

    什么是OVMF The Open Virtual Machine Firmware (OVMF) project aims to support firmware for Virtual Machin ...

  7. eclipse工具的使用心得

    一.eclipse工具的使用 eclipse是一个开源的IDE,进行javaEE开发一般使用myeclipse插件比较方便 1. java代码的位置 1)选择工作空间workspace 选择一个文件夹 ...

  8. CSDN Android客户端的制作 导航帖

    弄个导航贴,把相关知识来个汇总. CSDN Android的客户端的效果图: 分别通过以下博客进行详细的讲解: 1.Android 使用Fragment,ViewPagerIndicator 制作cs ...

  9. 把一个机器上1天内新增的文件用rsync传送到另外一台机器

    我的shell很菜,只好用shell和php结合来做 1.查找新增的文件,构造rsync的参数,把结果写入到log中 find /data/bmob/test/teststorage/data/ -m ...

  10. Mave手动安装jar包

    今天配置Maven项目时有一个相应的jdbc驱动jar包导不进去,就自己导入了. 首先在官网上下载该jar包,地址为http://mvnrepository.com/ 点击jar下载. 用maven命 ...