last modified by coder4

, 2019/08/30 18:34:26

Mockito 单元测试打桩神器

单元测试

软件测试是软件质量保证的关健环节,代表了需求、设计和编码的最终检查。

如上图所示,测试金字塔将测试分为三类

单元测试: 由开发者自行编写,应当覆盖80%以上的场景。对微服务架构而言,主要是在单个微服务内部,对复杂业务逻辑,编写单元测试。

集成测试: 由测试人员编写,强调系统整体联动,多偏向业务可用性验证。如下单流程是否畅通,库存扣减是否成功。它的覆盖场景一般之占10%。

功能测试: 一些由单元测试、集成测试不好做的,通过功能测试完成,一般来说,这类不好自动化的,需要手动进行测试。由于测试成功很高,这类一般只覆盖5%的场景。

测试金字塔也向我们揭示了一个实时:单元测试是整个测试环节的根基,如果单元测试做不好,上层的集成测试、功能测试都会无从谈起。

遗憾的是,多数开发者都不具备编写单元测试的良好习惯,甚至缺乏编写单元的动力。

除了缺乏软件质量保障的意识外,"嫌麻烦"也是这类开发者面对单元测试的口头禅。

本节将介绍Mockito,这是一个单元测试的利器。Mockito的出现,让我们可以更加轻松地编写单元测试。

在介绍Mockito之前,先来解释下,我们为什么不推荐使用Spring Boot启动单元测试框架。

实际上,Spring Boot本身是提供了单元测试框架的,可以在JUnit中通过注解的配置,启动一个Spring上下文环境,并支持自动注入等功能,如果你感兴趣,可以参考这篇文档。

在实际工作中,我也尝试过上述方法,但效果却并不太好,主要原因是:

启动Spring Boot环境速度很慢,至少要3秒,而一般的单元测试都是毫秒级别。

依赖管理需要手动声明,随着业务不断升级,经常忘记维护单元测试中的依赖,导致单元测试无法正常执行。

基于上述原因,我强烈不推荐在单元测试中启动Spring Boot环境。

对于服务之间存在依赖关系的场景,建议直接使用Mockito的打桩(Mock)进行。

希望在仔细的阅读本节后,你也会爱上单元测试:-)

Mockito

在软件测试中,Mock指的是效仿、模仿。Mockito就是为了解决测试中的Mock问题而诞生的,它可以很好的解决单元测试中,由于不同类耦合而带来的难以测试的问题。

还是以上面Spring Boot环境为例子。假设我们要测试A类,而类A又调用了B类和C类。此时可能有两种选择:

手动构造B和C。

通过启动Spring环境,自动地注入B和C。

现在有了Mockito后,我们有了另外的思路:无需构造B和C,而是通过Mockito,"Mock"出B和C(构造符合接口但没有实现的类),由于我们要测试的是A类中的逻辑,只要检查A调用B和C的时机、次数、参数是否正确,就可以了。

我们通过一个例子,来说明mockito的用法。

首先是ServiceA和它的实现:

package com.coder4.lmsia.abc.server.service.intf;

/**

* @author coder4

*/

public interface ServiceA{

int methodA(int a, int b);

}

package com.coder4.lmsia.abc.server.service.impl;

import com.coder4.lmsia.abc.server.service.intf.ServiceA;

import com.coder4.lmsia.abc.server.service.intf.ServiceB;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

/**

* @author coder4

*/

@Service

public class ServiceAImpl implements ServiceA{

@Autowired

private ServiceB serviceB;

@Override

public int methodA(int a, int b){

if (a <= 10 && b <= 10) {

return a + b;

} else {

return serviceB.methodB(a, b);

}

}

}

然后是服务B和它的实现:

package com.coder4.lmsia.abc.server.service.intf;

/**

* @author coder4

*/

public interface ServiceB{

int methodB(int a, int b);

}

package com.coder4.lmsia.abc.server.service.impl;

import com.coder4.lmsia.abc.server.service.intf.ServiceB;

import org.springframework.stereotype.Service;

/**

* @author coder4

*/

@Service

public class ServiceBImpl implements ServiceB{

@Override

public int methodB(int a, int b){

return a * b;

}

}

我们总结一下功能:

在服务A中,若参数a和b都小于10,则返回求和结果,否则交给服务B处理。

在服务B中,直接返回参数a和b的乘积结果。

在编写单元测试前,先要引用对应的包,lmabc-server/build.gradle:

dependencies {

compile project(':lmsia-abc-common')

...

testCompile 'junit:junit:4.12'

testCompile 'org.mockito:mockito-all:1.9.5'

}

这里要指出的是,mockito本身还是需要单元测试框架才能运行的,我们这里用的是最常见的JUnit。

然后看一下单元测试

package com.coder4.lmsia.abc.server;

import com.coder4.lmsia.abc.server.service.impl.ServiceAImpl;

import com.coder4.lmsia.abc.server.service.intf.ServiceA;

import com.coder4.lmsia.abc.server.service.intf.ServiceB;

import org.junit.Assert;

import org.junit.Before;

import org.junit.Test;

import org.mockito.Mockito;

import org.mockito.internal.util.reflection.Whitebox;

import static org.hamcrest.CoreMatchers.is;

/**

* @author coder4

*/

public class ServiceATest{

private ServiceA serviceA;

private ServiceB serviceB;

@Before

public void before(){

serviceA = new ServiceAImpl();

serviceB = Mockito.mock(ServiceB.class);

Whitebox.setInternalState(serviceA, "serviceB", serviceB);

}

@Test

public void testBelow10(){

Assert.assertThat(serviceA.methodA(1, 1), is(2));

Mockito.verifyZeroInteractions(serviceB);

}

@Test

public void testAbove10(){

serviceA.methodA(100, 1);

Mockito.verify(serviceB).methodB(100, 1);

}

}

我们分步解释一下:

before: 初始化ServiceA,因为我们要测试这个,所以必须手动初始化。而ServiceB我们在A的测试并不关注,直接Mock一个,并通过Whitebox注入到服务A中。

testBelow10: 前面服务实现已经介绍过,当参数a和b都小于10的场景,是在ServiceA中直接求和。所以这里我们验证两个的和,然后验证下是不是没有"碰过"服务B(verifyZeroInteractions)

testAbove10: 当任何一个参数大于10时候,实际会走服务B。所以我们验证下是否调用了服务B,且参数恰好是传给A的就好。

怎么样,有了Mockito后,测试是不是变得有趣起来了:-)

官方文档中提供了更多有趣的例子,等待你的发掘。

Copyright © 2019 coder4.

All rights reserved.

linux打桩数框架,Mockito 单元测试打桩神器相关推荐

  1. 单元测试打桩,通俗易懂解释。

    在软件开发中的单元测试过程中,单元测试打桩通常是一种模拟或替代正在被测试的组件或系统的策略.在单元测试打桩过程中,测试代码使用一个"虚拟"实现来替代掉实际组件或系统的某些部分,从而 ...

  2. Linux USB驱动框架分析 【转】

    转自:http://blog.chinaunix.net/uid-11848011-id-96188.html 初次接触与OS相关的设备驱动编写,感觉还挺有意思的,为了不至于忘掉看过的东西,笔记跟总结 ...

  3. mockito单元测试示例_Mockito模拟示例

    mockito单元测试示例 Mockito mocking framework provides different ways to mock a class. Let's look at diffe ...

  4. platform框架--Linux MISC杂项框架--Linux INPUT子系统框架--串行集成电路总线I2C设备驱动框架--串行外设接口SPI 设备驱动框架---通用异步收发器UART驱动框架

    platform框架 input. pinctrl. gpio 子系统都是 Linux 内核针对某一类设备而创建的框架, input子系统是管理输入的子系统 pinctrl 子系统重点是设置 PIN( ...

  5. Linux内核Netfilter框架与实现

    近日的工作多多少少和Linux的流控有点关系,自打几年前知道有TC这么一个玩意儿并且多多少少理解了它的原理之后,我就没有再动过它,因为我不喜欢 TC命令行,实在是太繁琐了,iptables命令行也比较 ...

  6. Linux下数百种Windows软件的免费替代品列表

    Linux下数百种 Windows 软件的免费替代品列表 程序所执行任务的描述 Windows Linux 1) 网络连接 网页浏览器 微软 IE,网景 Netscape / Mozilla, Ope ...

  7. Linux内核Thermal框架详解十三、Thermal Governor(3)

    接前一篇文章Linux内核Thermal框架详解十二.Thermal Governor(2) 二.具体温控策略 上一篇文章介绍并详细分析了bang_bang governor的源码.本文介绍第2种温控 ...

  8. Linux内核Thermal框架详解十二、Thermal Governor(2)

    本文部分内容参考 万字长文 | Thermal框架源码剖析, Linux Thermal机制源码分析之框架概述_不捡风筝的玖伍贰柒的博客-CSDN博客, "热散由心静,凉生为室空" ...

  9. OS相关驱动 Linux USB驱动框架分析

    初次接触与OS相关的设备驱动编写,感觉还挺有意思的,为了不至于忘掉看过的东西,笔记跟总结当然不可缺,更何况我决定为嵌入式卖命了.好,言归正传,我说一说这段时间的收获,跟大家分享一下Linux的驱动开发 ...

最新文章

  1. saltstack使用指南----常用执行模块
  2. XML学习笔记之XML的简介
  3. fastadmin弹框提示不起作用 confirm
  4. 【转】Xcode7.1环境下上架iOS App到AppStore 流程 -- 不错!!
  5. 红茶一杯话Binder
  6. 上传图片文件(支持远程存储)
  7. 死磕java_死磕JavaScript-垃圾收集机制
  8. Exchange Server 2016管理系列课件50.DAG管理之激活数据库副本
  9. (转载) Android两个子线程之间通信
  10. AngularJS-源码阅读(八.二)
  11. PPC丢失后,手机信息如何保护?(C#)
  12. Lattice - 规划模块 1.采样轨迹 2.计算轨迹cost 3 循环检测筛选轨迹
  13. Optisystem中器件的学习(3-WDM Multiplexers Library/Optical Fibers Library/Amplifiers Library/Fiters Librar)
  14. Securing Android: A Survey, Taxonomy, and Challenges --论文笔记
  15. 知乎热议20年科研怪状:为何论文创新性越强越难发表,跟风修修补补反而更容易发?
  16. 360与QQ大战,网友昨晚热论看大片
  17. 盛世昊通解析为什么你买不到想要的新能源汽车
  18. Vufroia相机对焦问题
  19. cocos2d-x创建新项目模板
  20. (转)牛顿和哈雷的故事(重点看一下牛顿老时候)

热门文章

  1. SpringCloud-06-Hystrix断路器
  2. 液晶显示模块制作生产流程
  3. 过滤器,监听器,拦截器的区别
  4. 用js实现点击链接跳转APP对应页面
  5. 在人心惶惶的互联网寒冬之季,值得看看《大佛普拉斯》
  6. 浅谈802.15.4协议
  7. LeetCode第 764 题:最大加号标志(C++)
  8. Codeforces Round #764 (Div. 3)部分题解
  9. matlab2018a安装(里面有matlab2018a_win64的下载路径以及详细步骤,自己亲自测试运行没有问题!)
  10. EC11旋转编码器驱动程序