是什么
mock测试就是在测试过程中中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法。
Mock通常是指,在测试一个对象A时,我们构造一些假的对象来模拟与A之间的交互,而这些Mock对象的行为是我们事先设定且符合预期。通过这些Mock对象来测试A在正常逻辑,异常逻辑或压力情况下工作是否正常。
隔绝其他模块出错引起本模块的测试错误。
隔绝其他模块的开发状态,只要定义好接口,不用管他们开发有没有完成。
一些速度较慢的操作,可以用Mock Object代替,快速返回。 对于分布式系统的测试,使用Mock Object会有另外两项很重要的收益:
通过Mock Object可以将一些分布式测试转化为本地的测试
将Mock用于压力测试,可以解决测试集群无法模拟线上集群大规模下的压力
在使用Mock的过程中,发现Mock是有一些通用性的,对于一些应用场景,是非常适合使用Mock的:
-
真实对象具有不可确定的行为(产生不可预测的结果,如股票的行情)
-
真实对象很难被创建(比如具体的web容器)
-
真实对象的某些行为很难触发(比如网络错误)
-
真实情况令程序的运行速度很慢- 真实对象有用户界面 测试需要询问真实对象它是如何被调用的(比如测试可能需要验证某个回调函数是否被调用了) 真实对象实际上并不存在(当需要和其他开发小组,或者新的硬件系统打交道的时候,这是一个普遍的问题) 当然,也有一些不得不Mock的场景: 一些比较难构造的Object:这类Object通常有很多依赖,在单元测试中构造出这样类通常花费的成本太大。 执行操作的时间较长Object:有一些Object的操作费时,而被测对象依赖于这一个操作的执行结果,例如大文件写操作,数据的更新等等,出于测试的需求,通常将这类操作进行Mock。 异常逻辑:一些异常的逻辑往往在正常测试中是很难触发的,通过Mock可以人为的控制触发异常逻辑。 在一些压力测试的场景下,也不得不使用Mock,例如在分布式系统测试中,通常需要测试一些单点(如namenode,jobtracker)在压力场景下的工作是否正常。而通常测试集群在正常逻辑下无法提供足够的压力(主要原因是受限于机器数量),这时候就需要应用Mock去满足。
测试的对象一般称之为SUT(Software Under Test),mock 的作用是模拟 SUT 依赖对象的行为。
为什么
为什么需要模拟 B 的行为呢?
-
(1)提高 A 的测试覆盖率。A 依赖 B,本质上依赖的是 B 的返回结果,也就是说 B 的返回结果会影响 A 的行为。通过 mock B 我们可以构造各种正常和异常的来自 B 的返回结果,从而更充分测试 A 的行为。
-
(2)避免 B 的因素从而对 A 产生影响。依赖真实的 B 去测试 A 可能有很多问题:B 的开发没有完成时无法测试 A;B 有阻塞性bug 时无法测试 A;B 的依赖 C 有阻塞性 bug 时无法测试 A;
-
(3)提高 A 的测试效率。B 的真实行为可能很慢,而 B 的模拟行为是非常快的,因此可以加快 A 的测试执行速度。
怎么做
常见mock方法
- (1)方法级别 mock:mock 的对象是一个函数调用,例如获取系统环境变量。
- (2)类级别 mock:mock 的对象是一个类,例如一个 HTTP server。
- (3)接口级别 mock:mock 的对象是一个 API 接口。
- (4)服务级别 mock:mock 的对象是整个服务。比如前端工程师自测试时,可以讲后端整个服务都 mock 掉,这其实等同于将后端的所有接口都 mock。
常用mock测试工具
单元测试级别
这个级别的mock工具有easymock、jMock、Mockito、Unitils Mock、PowerMock、JMockit等,关于各自优劣势大家可以上网查询。
单元测试mock
最初,mock主要应用在单元测试中,因为单元测试的目的是只想针对自己关注的这个"单元"部分进行测试,所以需要对屏蔽掉一些外部依赖的影响,这时候就可以使用mock技术。
\
之所以要在测试中使用Mock对象,其实有很多原因,其中最重要的原因就是真实对象的构造成本太高。这时候一般就会采用mock对象。
而市面上也有很多工具可以方便的帮助我们进行单元测试的mock,如Easymock、jMock、Mockito、Unitils Mock、PowerMock、JMockit等。
其中比较常用的就是Easymock(easymock.org/ )、JMockit(jmockit.github.io/index.html )和Mockito(site.mockito.org/ )这三种,用起来都比较简单。
\
接口测试级别
接口级别的mock工具完成的主要功能是对一个用户的请求,模拟server返回一个接口的响应数据。常用的有: - Wiremock - Mockserver - Moco - Mock.js - RAP
接口mock:如我们的要测试的一个方法,其中依赖了一个RPC远程服务,因为远程服务的返回值可能是各种各样的,我们为了测试我们的接口的鲁棒性,就会针对各种边界情况进行充分测试。
如果把外部接口mock掉,也就是把外部接口的返回值当做一个mock对象,那么我们就可以很方便的模拟各种情况。如外部接口正常返回、异常返回、请求超时等等,都可以很方便的被测试。
,比如日常开发环境调用支付宝,我们需要经常构造诸如协议过期、余额不足、请求超时、账户不存在等case的时候,就可以想办法将他们的接口mock掉。
市面上现在也有很多接口mock工具可以使用,如RAP、Yapi、Moco和DOClever等。
(1)不要过度使用 mock。测试用例中掌握好使用 mock 的度。在涉及网络访问、数据库读写、操作系统交互等系统级调用,优先使用 mock。
(2)不要过度依赖基于 mock 的测试结果。基于 mock 的测试无论多么充分,这都不能保证不出现问题的遗漏。一个完整的测试策略一定是由基于 mock 的测试和基于非 mock 的测试共同组成的,二者相辅相成缺一不可。