您的位置:首页 > 其它

【接口测试】接口mock之基础知识

2017-06-27 22:59 225 查看
 Mock:In object-oriented programming, mockobjects are simulated objects that
mimic the behavior of real objects incontrolled ways. A computer programmer typically creates a mock object to testthe behavior of some other object, in much the same way that a car designeruses a crash test dummy to simulate the dynamic behavior. of a human
in vehicleimpacts.

一、Mock操作方式的好处
  Mock通常是指,在测试一个对象A时,我们构造一些假的对象来模拟与A之间的交互,而这些Mock对象的行为是我们事先设定且符合预期。通过这些Mock对象来测试A在正常逻辑,异常逻辑或压力情况下工作是否正常。
引入Mock最大的优势在于:Mock的行为固定,它确保当你访问该Mock的某个方法时总是能够获得一个没有任何逻辑的直接就返回的预期结果。
Mock Object的使用通常会带来以下一些好处:

隔绝其他模块出错引起本模块的测试错误。
隔绝其他模块的开发状态,只要定义好接口,不用管他们开发有没有完成。
一些速度较慢的操作,可以用Mock Object代替,快速返回。
对于分布式系统的测试,使用Mock Object会有另外两项很重要的收益。
通过Mock Object可以将一些分布式测试转化为本地的测试。
将Mock用于压力测试,可以解决测试集群无法模拟线上集群大规模下的压力。

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

真实对象具有不可确定的行为(产生不可预测的结果,如股票的行情)
真实对象很难被创建(比如具体的web容器)
真实对象的某些行为很难触发(比如网络错误)
真实情况令程序的运行速度很慢
真实对象有用户界面
测试需要询问真实对象它是如何被调用的(比如测试可能需要验证某个回调函数是否被调用了)
真实对象实际上并不存在(当需要和其他开发小组,或者新的硬件系统打交道的时候,这是一个普遍的问题)
当然,也有一些不得不Mock的场景:
一些比较难构造的Object:这类Object通常有很多依赖,在单元测试中构造出这样类通常花费的成本太大。
执行操作的时间较长Object:有一些Object的操作费时,而被测对象依赖于这一个操作的执行结果,例如大文件写操作,数据的更新等等,出于测试的需求,通常将这类操作进行Mock。
异常逻辑:一些异常的逻辑往往在正常测试中是很难触发的,通过Mock可以人为的控制触发异常逻辑。

  在一些压力测试的场景下,也不得不使用Mock,例如在分布式系统测试中,通常需要测试一些单点(如namenode,jobtracker)在压力场景下的工作是否正常。而通常测试集群在正常逻辑下无法提供足够的压力(主要原因是受限于机器数量),这时候就需要应用Mock去满足。
在这些场景下,我们应该如何去做Mock的工作了,一些现有的Mock工具可以帮助我们进行Mock工作。
三、Mock操作相关工具介绍
  手动的构造 Mock 对象通常带来额外的编码量,而且这些为创建 Mock对象而编写的代码很有可能引入错误。目前,有许多开源项目对动态构建 Mock对象提供了支持,这些项目能够根据现有的接口或类动态生成,这样不仅能避免额外的编码工作,同时也降低了引入错误的可能。

C++: GoogleMock http://code.google.com/p/googlemock/
Java: EasyMock http://easymock.org/
API 管理平台 XXL-API - V2EX:https://github.com/xuxueli/xxl-api
RAP:https://github.com/thx/RAP/wiki/home_cn
网易NEI:https://nei.netease.com/
WireMock:http://wiremock.org/

通常Mock工具通过简单的方法对于给定的接口生成 Mock对象的类库。它提供对接口的模拟,能够通过录制、回放、检查三步来完成大体的测试过程,可以验证方法的调用种类、次数、顺序,可以令 Mock对象返回指定的值或抛出指定异常。通过这些Mock工具我们可以方便的构造 M
d9a5
ock 对象从而使单元测试顺利进行,能够应用于更加复杂的测试场景。
以EasyMock为例,通过 EasyMock,我们可以为指定的接口动态的创建 Mock 对象,并利用Mock 对象来模拟协同模块,从而使单元测试顺利进行。这个过程大致可以划分为以下几个步骤:

使用 EasyMock 生成 Mock 对象
设定 Mock
对象的预期行为和输出 
将 Mock
对象切换到 Replay
状态
调用 Mock
对象方法进行单元测试
对 Mock
对象的行为进行验证

  EasyMock的使用和原理: http://www.ibm.com/developerworks/cn/opensource/os-cn-easymock/
  EasyMock 后台处理的主要原理是利用 java.lang.reflect.Proxy为指定的接口创建一个动态代理,这个动态代理,就是我们在编码中用到的 Mock 对象。EasyMock 还为这个动态代理提供了一个InvocationHandler 接口的实现,这个实现类的主要功能就是将动态代理的预期行为记录在某个映射表中和在实际调用时从这个映射表中取出预期输出。
借助类似于EasyMock这样工具,大大降低了编写Mock对象的成本,通常来说Mock工具依赖于单元测试框架,为用户编写TestCase提供便利,但是本身依赖于单元测试框架去驱动,管理case,以及收集测试结果。例如EasyMock依赖于JUint,GoogleMock依赖于Gtest。
那么有了单元测试框架和相应的Mock工具就万事俱备了,还有什么样的问题?正如单元测试框架没有告诉你如何写TestCase一样,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