原文地址:https://www.codeproject.com/articles/516360/mockito-a-great-mock-framework-for-java-developmen

Mockito是一个讽刺的框架,味道非常好。它允许您使用干净简单的API编写漂亮的测试。

介绍

这个艺术将展示mock框架的一些基本概念,为什么我们应该使用它,并演绎一个在Java中应用Mockito的简单方法。

Mock的概念

在软件开发世界之外,术语“ mock ”意味着模仿或模拟。 因此,“ mock ”可以被认为是一种独立的,冒名顶生的,或者最常被称之为软件开发,一种fake 。

假货经常被用作待测类的依赖关系。

条款和定义
依赖关系 - 依赖关系是指应用程序中的一个类别依赖于另一个类来执行其预期功能。 依赖关系通常存储在依赖类中的实例变量中。
 
被试课程 - 在进行单元测试时,术语“单元”通常是指一个单独的类,特别是测试写入的类。 因此,被测试类是正在测试的应用程序类。

为什么模拟?

当我们学习编程时,我们的对象通常是自包含的。 任何你好的世界都没有依赖于外部类(System.out),也不会在学习语言的过程中写入许多其他类。 然而,在现实世界中,软件具有依赖性。 我们有依赖于数据访问对象(DAO)的服务和服务的操作类,列表继续。

单元测试的想法是我们要测试我们的代码而不测试依赖。 此测试允许您验证正在测试的代码是否工作,而不管其是否依赖。 理论是,如果我写的代码按照设计工作,我的依赖关系按照设计工作,那么他们应该按照设计一起工作。 下面的代码将是一个例子:

HideCopy Code
import java.util.ArrayList;
public class Counter {public Counter() {}public int count(ArrayList items) {int results = 0;for(Object curItem : items) {results ++;}return results;}
}

我知道上面的例子就像你所得到的一样简单,但是它说明了一点。 如果您想测试方法计数,您将在测试中写入,以解决计数方法的工作原理。 您不是试图测试ArrayList的工作原理,因为您假设它已经过测试并按照设计工作 。您唯一的目标是测试您对ArrayList的使用。

模拟对象背后的概念是我们想要创建一个取代真实对象的对象。 这个模拟对象将期望使用某些参数调用某种方法,而在这种情况下, 它将返回一个预期的结果。

什么是关键的Mock概念?

当谈到mock时,你只需要3件事情就需要担心; 扼杀,设定期望和验证。 某些单元测试场景不涉及任何这些情况,其他单独测试场景只涉及桩杆,而其他则涉及设置预期和验证。

存根

Stubbing是告诉你的假的过程,当它与它进行交互时如何表现。 您通常可以存放公共属性(带有getter和/或setter的公共属性)和公共函数。

说到stubbing功能,你通常有很多选择。 您可能希望返回特定值,抛出错误或调度事件。 此外,您可能希望指示函数的行为方式取决于调用方式(即通过匹配传递给函数的参数的类型或值)。

如果这听起来像是很多的工作,它可以是,但它一般不是。 许多mock框架的一个很大的特点是你不需要stub void函数。 您也不必在执行测试过程中存储任何未被调用的函数或未查询的属性。

设定期望

假冒的主要特征之一就是能够告诉假冒测试运行时的期望。 例如,您可能希望调用一个特定的函数3次。 你可能期望它永远不会被调用。 您可能希望它至少被调用两次,但不要超过5次。 您可能希望使用特定类型的参数或特定值或上述任何组合来调用它。 可能性是无止境的。

设定期望是告诉你假的你会发生什么的过程。 记住,由于它是假的,实际上没有发生。 但是,你被测试的班级并不聪明。 从它的角度来看,它调用了这个函数,并期望它做了它应该做的任何事情。

对于什么是值得的,大多数嘲笑框架可以让您创建接口或公共类的模拟。 您不限于仅仅模拟接口。

验证

设定期望和验证是并存的。 在调用被测试类的函数之前,设置期望值。 验证完成。 所以,首先你设定了期望,然后验证你的期望是否得到满足。

从单元测试的角度来看,如果您的期望未得到满足,则单元测试失败。 例如,如果您设置了ILoginService.login函数应该使用特定的用户名和密码一次调用的期望,但是在执行测试期间它并没有被调用,则该伪造不会被验证,并且测试失败。

Mock的好处是什么?

 您可以提前创建测试; TDD

这一个是更强大的好处之一。 如果您创建一个模拟器,您可以在服务创建之前编写服务测试,使您能够在开发过程中将测试添加到自动化环境中。 换句话说,Service Mocking可以让您使用测试驱动开发。

 团队可以并行工作

这与上述类似 为不存在的代码创建测试。 但是以前的一点是针对开发人员编写测试,这是针对测试团队的。 当您没有任何测试时,团队如何开始创建测试? 模拟它,并对模拟器进行测试! 这意味着当服务准备好进行测试时,QA团队实际上可以准备一整套测试; 我们没有停机的时候,一个队伍等待另一个完成。 这使得嘲弄的财务论据特别强。

 您可以创建概念或演示的证明。

由于Mocks可以(成本最高)能够实现成本效益,因此可以使用Mocks来创建概念证明,线框架,或作为您正在考虑构建的应用程序的演示。 这是非常强大的,为决定是否继续开发项目做出决定,但最重要的是为实际设计决策提供了良好的基础。

 您可以编写测试资源不可访问

这是不属于实际利益类别的好处之一,而是作为救生员。 曾经想要测试或使用服务,只是被告知该服务是在防火墙后面,那个防火墙无法为您打开,或者您被授权使用该防火墙? 当你这样做时,一个MockService放置在可访问的地方,包括在你本地的电脑上,是一个救命的人。

 模拟器可以交付给客户

有些情况下,您无法允许访问外部来源的测试系统(如合作伙伴或客户)的原因。 这些原因可以是访问安全性,信息敏感性,或只是测试环境可能无法24/7访问的事实。 在这些情况下 您如何为您的合作伙伴或客户提供测试系统以开始开发或测试? 一个简单的解决方案是从您的网络或客户自己的网络提供一个模拟。 soapUI模拟是非常容易部署的,它可以在soapUI中运行,也可以作为.WAR文件导出,并放置在您选择的Java服务器中。

 您可以隔离系统

有时您想测试系统的一部分,而不会影响其他系统部件。 这是因为其他系统会对测试数据增加噪音,使得从收集的数据中得出更好的结论更加困难。 使用mocks,您可以删除所有的系统,嘲笑所有系统,除了您在测试中需要确定的一个系统。 当进行嘲讽隔离时,这些嘲弄可以做得非常简单但可靠,快速,可预测。 这给您一个测试环境,您已经删除了所有随机行为,具有可重复的模式,并可以很好地监控特定系统。

Mockito框架

Mockito是根据MIT许可证发布的Java开源测试框架。 
Mockito通过允许开发人员预先确定被测系统(SUT)的行为来区别于其他嘲笑框架。[4] 对模拟对象的批评之一是测试代码与被测系统的紧密耦合。[5] 由于Mockito试图通过消除预期的规范来消除预期运行验证模式[6],所以耦合被减小或最小化。 这个区别功能的结果是更简单的测试代码,应该更容易阅读和修改。

您可以验证互动:

HideCopy Code
// mock creation
List mockedList = mock(List.class);
// using mock object
mockedList.add("one");
mockedList.clear();
// selective and explicit vertification
verify(mockedList).add("one");
verify(mockedList).clear();

或存根方法调用

HideCopy Code
// you can mock concrete class, not only interfaces
LinkedList mockedList = mock(LinkedList.class);
// stubbing - before execution
when(mockedList.get(0)).thenReturn("first");
// following prints "first"
System.out.println(mockedList.get(0));
// following prints "null" because get(999) was not stubbed.
System.out.println(mockedList.get(999));

使用Mockito的简单示例Java代码


没有Mock框架


用Mockito框架

步骤1:在Eclipse中创建一个Maven项目

定义pom.xml如下:

HideShrinkCopy Code
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>vn.com.phatbeo.ut.mockito.demo</groupId><artifactId>demoMockito</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>demoMockito</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><build><sourceDirectory>src</sourceDirectory><testSourceDirectory>test</testSourceDirectory><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>2.3.1</version><configuration><source>1.6</source><target>1.6</target></configuration></plugin></plugins></build><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.8.1</version><scope>test</scope></dependency><dependency><groupId>org.mockito</groupId><artifactId>mockito-all</artifactId><version>1.8.5</version><scope>test</scope></dependency></dependencies></project> 

步骤2:添加java源代码

Person.java

HideCopy Code
  package vn.com.enclave.phatbeo.ut.mockito.demo;
/** * @author Phat (Phillip) H. VU <vuhongphat@hotmail.com>*  */
public class Person
{private final Integer personID;private final String personName;public Person( Integer personID, String personName ){this.personID = personID;this.personName = personName;}public Integer getPersonID(){return personID;}public String getPersonName(){return personName;}
}

接口PersonDAO.java

HideCopy Code
 package vn.com.enclave.phatbeo.ut.mockito.demo;
/*** @author Phat (Phillip) H. VU <vuhongphat@hotmail.com>* */
public interface PersonDao
{public Person fetchPerson( Integer personID );public void update( Person person );
}

PersonService.java

HideShrinkCopy Code
  package vn.com.enclave.phatbeo.ut.mockito.demo;
/*** @author Phat (Phillip) H. VU <vuhongphat@hotmail.com>* */
public class PersonService
{private final PersonDao personDao;public PersonService( PersonDao personDao ){this.personDao = personDao;}public boolean update( Integer personId, String name ){Person person = personDao.fetchPerson( personId );if( person != null ){Person updatedPerson = new Person( person.getPersonID(), name );personDao.update( updatedPerson );return true;}else{return false;}}
}

步骤3:添加单元测试类。

然后,跳转到PersonService.java类的单元测试用例

假设类PersionServiceTest.java如下所示:

HideShrinkCopy Code
 package vn.com.enclave.phatbeo.ut.mockito.demo.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
/*** @author Phat (Phillip) H. VU <vuhongphat@hotmail.com>* */
public class PersonServiceTest
{@Mockprivate PersonDao personDAO;private PersonService personService;@Beforepublic void setUp()throws Exception{MockitoAnnotations.initMocks( this );personService = new PersonService( personDAO );}@Testpublic void shouldUpdatePersonName(){Person person = new Person( 1, "Phillip" );when( personDAO.fetchPerson( 1 ) ).thenReturn( person );boolean updated = personService.update( 1, "David" );assertTrue( updated );verify( personDAO ).fetchPerson( 1 );ArgumentCaptor<Person> personCaptor = ArgumentCaptor.forClass( Person.class );verify( personDAO ).update( personCaptor.capture() );Person updatedPerson = personCaptor.getValue();assertEquals( "David", updatedPerson.getPersonName() );// asserts that during the test, there are no other calls to the mock object.verifyNoMoreInteractions( personDAO );}@Testpublic void shouldNotUpdateIfPersonNotFound(){when( personDAO.fetchPerson( 1 ) ).thenReturn( null );boolean updated = personService.update( 1, "David" );assertFalse( updated );verify( personDAO ).fetchPerson( 1 );verifyZeroInteractions( personDAO );verifyNoMoreInteractions( personDAO );}
}

兴趣点

+什么是Mock框架在概述。

+为什么我们在Java开发中使用Mockito进行测试。

参考文献

http://java.dzone.com/articles/the-concept-mocking

http://en.wikipedia.org/wiki/Mockito

http://code.google.com/p/mockito/

历史

2012年12月26日首发

执照

本文以及任何相关的源代码和文件均已获得“代码项目开放许可证(CPOL)”许可.

Mockito一个用于Java开发的伟大的模拟框架相关推荐

  1. 用于Java开发机器学习和深度学习的Vector API(翻译)

    本文介绍了用于Java开发机器学习和深度学习的Vector API 英语原文链接 https://software.intel.com/en-us/articles/vector-api-develo ...

  2. Mockito:一个强大的用于Java开发的模拟测试框架

    介绍 本文将介绍模拟测试框架Mockito的一些基础概念, 介绍该框架的优点,讲解应用Mockito的Java示例. 模拟(Mock)的概念 在软件开发的世界之外, "mock"一 ...

  3. 精选10个用于Java开发Spring Boot的Eclipse插件

    前言 作为从事Java多年的程序员,在此分享用于 Java 和 Spring Boot 开发的 10 大 Eclipse插件: 1. EGit - Eclipse 的 Git 集成 这可能是当今 Ja ...

  4. JAVA三维可视化组件:Matplot 3D for JAVA(V3.0) 一个纯JAVA开发的科学数据可视化组件包 类似 Python 的matplotlib(含示例代码)

    目录 概述 组件下载及项目地址 效果展示和示例代码 概述 Matplot3D for JAVA(V3.0) 是一个基于JAVA SE 1.8环境开发的三维图形图表组件. 组件由纯JAVA SE 实现( ...

  5. 个人总结的一个中高级Java开发工程师或架构师需要掌握的一些技能...

    近三年,其实都是在做一个项目,项目是一个大型的多节点部署的项目,做了好几个版本,中间用到了很多技术和框架, 也用了一些管理工具和敏捷实践.我这里不是来说项目的,因为最近看了一些招聘信息,结合项目中用到 ...

  6. 一个用于 Angular 开发的 Chrome 扩展 - Angular Dev Tools

    该扩展安装到 Chrome 浏览器之后,Chrome 开发者工具会多出一个标签页: 可以在 Component 面板里查看 Component 的属性,或者直接对其修改: 在 Component 面板 ...

  7. POI技术—用于java开发解析excel的抽象类

    1.单元格各类型数据读取 1.1 基本类型 处理的Excel数据包括字符型数据,数字.日期.公式等. 下面是单元格类型说明: 2实例 解析excel中数据,要求转换为文本方式存储 2.1 写一个exc ...

  8. Java开发初体验:第一个Java程序:HelloWorld

    文章目录 2.1 java语言的环境搭建 2.2 开发体验:HelloWorld 2.3 注释(Comment) 2.4 Java API文档 2.5 常用的Java开发工具(Integrated D ...

  9. java 开发新技术

    最近在网上查资料碰到好多没接触过的技术,先汇总在这里备用,以后慢慢吸收 1. JNA JNI的替代品,调用方式比JNI更直接,不再需要JNI那层中间接口,几乎达到Java直接调用动态库 2. Smal ...

最新文章

  1. 阿里巴巴图学习框架 euler 安装运行记录
  2. java 遍历list 性能_java list三种遍历方法性能比較
  3. shell 脚本调试
  4. JAVA_OA管理系统(三)番外篇:Myeclipse导入Spring源码包
  5. 7-3 作业调度算法--高响应比优先 (40 分)(思路+详解+vector容器做法)Come Baby!!!!!
  6. ES6中的迭代器(Iterator)和生成器(Generator)(一)
  7. 什么样的人适合做自动化测试
  8. r语言 悲观剪枝_【R语言新书】前言Ⅲ—R语言编程思想
  9. VC MakeUp 操作XML
  10. c# 循环com,分别对串口写入与读取,获取需要的串口信息
  11. php和apache配置 LoadModule php5_module D:/php/php5apache2.dll
  12. CSDN-markdown(文字加色加字号、背景色等)
  13. 基于C/C++语言的停车场管理系统编程课程设计超详细
  14. 视频监控系统中H.265、SVAC、GB/T28181、ONVIF、PSIA有什么区别?
  15. Java 泛型是如何工作的?类型擦除是什么?
  16. 运动模糊运动拖影果冻效应分析
  17. matlab fkine,Matlab Robotics ToolBox 实战 -- 七次多项式取放轨迹规划
  18. 2021安徽省高考成绩排名查询,2021年安徽高考成绩排名查询系统,安徽高考位次排名表...
  19. vue 实现级联选择器
  20. netbeans 代码对齐_加快开发速度:NetBeans代码模板,AutoHotKey和Ditto

热门文章

  1. 最新勒索病毒扩展名.actin,.2k19sys,.help,.lanset的特征分析,常见处理方式
  2. QQ2006beta2sp3forsp1的下载地址
  3. 计算机休眠策略,桌面从睡眠或休眠中意外唤醒
  4. 编译caffe时,遇到问题:无法打开文件“libboost_thread-vc120-mt-gd-1_58.lib
  5. IOS开发环境 Xcode 下载 安装
  6. java基础面试资料收集篇一
  7. 相对定位和绝对定位的搭配使用
  8. 吕鑫的Ado数据库函数
  9. Kinect v2.0原理介绍之八:高清面部帧(1) FACS 介绍
  10. 生意参谋获取数据系列章节