您的位置:首页 > 其它

单元测试之Mock

2015-06-03 14:48 274 查看
Mock测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法。

引入Mock最大的优势在于:Mock的行为固定,它确保当你访问该Mock的某个方法时总是能够获得一个没有任何逻辑的直接就返回的预期结果。

Mock Object的使用通常会带来以下一些好处:

1.隔绝其他模块出错引起本模块的测试错误。

2.隔绝其他模块的开发状态,只要定义好接口,不用管他们开发有没有完成。

3.一些速度较慢的操作,可以用Mock Object代替,快速返回。

对于分布式系统的测试,使用Mock Object会有另外两项很重要的收益:

1.通过Mock Object可以将一些分布式测试转化为本地的测试

2.将Mock用于压力测试,可以解决测试集群无法模拟线上集群大规模下的压力
应用场景

在使用Mock的过程中,发现Mock是有一些通用性的,对于一些应用场景,是非常适合使用Mock的:

1.真实对象具有不可确定的行为(产生不可预测的结果,如股票的行情)

2.真实对象很难被创建(比如具体的web容器)

3.真实对象的某些行为很难触发(比如网络错误)

4.真实情况令程序的运行速度很慢

5.真实对象有用户界面

6.测试需要询问真实对象它是如何被调用的(比如测试可能需要验证某个回调函数是否被调用了)

7.真实对象实际上并不存在(当需要和其他开发小组,或者新的硬件系统打交道的时候,这是一个普遍的问题)

当然,也有一些不得不Mock的场景:一些比较难构造的Object:这类Object通常有很多依赖,在单元测试中构造出这样类通常花费的成本太大。 执行操作的时间较长Object:有一些Object的操作费时,而被测对象依赖于这一个操作的执行结果,例如大文件写操作,数据的更新等等,出于测试的需求,通常将这类操作进行Mock。

异常逻辑:一些异常的逻辑往往在正常测试中是很难触发的,通过Mock可以人为的控制触发异常逻辑。

在一些压力测试的场景下,也不得不使用Mock,例如在分布式系统测试中,通常需要测试一些单点(如namenode,jobtracker)在压力场景下的工作是否正常。而通常测试集群在正常逻辑下无法提供足够的压力(主要原因是受限于机器数量),这时候就需要应用Mock去满足。

在这些场景下,我们应该如何去做Mock的工作了,一些现有的Mock工具可以帮助我们进行Mock工作。
选择恰当的mock点

对于Mock这里存在两个误区,

1.是Mock的对象越多越好;

2.Mock会引入巨大的工作量,通常得不偿失。这都是源于不恰当的Mock点的选取。

这里说的如何选择恰当的mock点,是说对于一个被测对象,我们应当在外围选择恰当的mock对象,以及需要mock的接口。因为对于任意一个对象,任意一段代码逻辑我们都是有办法进行Mock的,而Mock点选择直接决定了我们Mock的工作量以及测试效果。从另外一种意义上来说,不恰当Mock选择反而会对我们的测试产生误导,从而在后期的集成和系统测试中引入更多的问题。

在mock点的选择过程中,以下的一些点会是一些不错的选择:

网络交互:如果两个被测模块之间是通过网络进行交互的,那么对于网络交互进行Mock通常是比较合适的,如RPC

外部资源:比如文件系统、数据源,如果被测对象对此类外部资源依赖性非常强,而其行为的不可预测性很可能导致测试的随机失败,此类的外部资源也适合进行Mock。

UI:因为UI很多时候都是用户行为触发事件,系统本身只是对这些触发事件进行相应,对这类UI做Mock,往往能够实现很好的收益,很多基于关键字驱动的框架都是基于UI进行Mock的

第三方API:当接口属于使用者,通过Mock该接口来确定测试使用者与接口的交互。

当然如何做Mock一定是与被系统的特性精密关联的,一些强制性的约束和规范是不合适的。这里介绍几个做的比较好的mock的例子。
Mock工具的介绍

Mock工具有EasyMock、jMock、Mockito、PowerMock、jmockit、Unitils等工具。
1.EasyMock

EasyMock 是一套通过简单的方法对于指定的接口或类生成 Mock 对象的类库,它能利用对接口或类的模拟来辅助单元测试。本文将对 EasyMock 的功能和原理进行介绍,并通过示例来说明如何使用 EasyMock 进行单元测试。

官方:http://www.easymock.org/

教程:

1)EasyMock 使用方法与原理剖析

2)使用 EasyMock 更轻松地进行测试
2.jMock

JMock是帮助创建mock对象的工具,它基于Java开发,在Java测试与开发环境中有不可比拟的优势,更重要的是,它大大简化了虚拟对象的使用。

JMock是一个使用模拟对象机制测试Java代码的开发包。模拟对象(Mock Object)可以取代真实对象的位置,用于测试一些与真实对象进行交互或依赖于真实对象的功能,模拟对象的背后目的就是创建一个轻量级的、可控制的对象来代替测试中需要的真实对象,模拟真实对象的行为和功能,方便我们的测试。JMock就是这种机制的实现,使用JMock我们可以快速创建模拟对象,定义交互过程中的约束条件等,同时JMock也是易扩展的,你可以很方便添加自定义的需求。

官网:http://jmock.org/

教程:

1)使用jmock对HttpServlet类进行单元测试

2)jmock2.5基本教程
3.Mockito

Mockito是一个针对Java的mocking框架。它与EasyMock和jMock很相似,但是通过在执行后校验什么已经被调用,它消除了对期望行为(expectations)的需要。其它的mocking库需要你在执行前记录期望行为(expectations),而这导致了丑陋的初始化代码。

项目地址:https://github.com/mockito/mockito

教程:

1)强大的Mockito测试框架

2)mockito简单教程
4.PowerMock

PowerMock 也是一个单元测试模拟框架,它是在其它单元测试模拟框架的基础上做出的扩展。通过提供定制的类加载器以及一些字节码篡改技巧的应用,PowerMock现了对静态方法、构造方法、私有方法以及 Final 方法的模拟支持,对静态初始化过程的移除等强大的功能。因为 PowerMock在扩展功能时完全采用和被扩展的框架相同的 API, 熟悉PowerMock 所支持的模拟框架的开发者会发现 PowerMock 非常容易上手。PowerMock的目的就是在当前已经被大家所熟悉的接口上通过添加极少的方法和注释来实现额外的功能,目前,PowerMock
仅支持 EasyMock 和 Mockito。

官网:http://www.powermock.org

项目地址:https://github.com/jayway/powermock

教程:

1)PowerMock介绍

2)一个牛x的mock框架--Powermock

3)PowerMock实战手册
5.JMockit 

JMockit是google code上面的一个java单元测试mock项目,她很方便地让你对单元测试中的final类,静态方法,构造方法进行mock,功能强大。它(完全基于 Java 5 SE 的 java.lang.instrument 包开发,内部使用 ASM 库来修改Java的Bytecode。

官网:http://jmockit.org/

教程:

1)单元测试mock框架——jmockit实战

2)使用JMockit编写java单元测试
6.Unitils

Unitils构建在DBUnit与EasyMock项目之上并与JUnit和TestNG相结合。支持数据库测试,支持利用mock对象进行测试并提供与Spring和Hibernate相集成。Unitils设计成以一种高度可配置和松散偶合的方式来添加这些服务到单元测试中。

官网:http://www.unitils.org

教程:

1)Unitils 学习笔记

2)Unitils教程

3)Unitils的简单实用

参考文章:

1.Java 各种Mock工具比较

2.有效使用Mock编写java单元测试
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  单元测试 mock