1. 背景

在实际产品开发过程中,某个服务或前端依赖一个服务接口,该接口可能依赖多个底层服务或模块,或第三方接口,比如说服务 A 依赖服务B,服务B又依赖服务 C,如下图所示:

这种依赖的问题会导致原本的需求目的是要验证服务A,但由于所依赖的服务B或者服务C不稳定或者未开发完成,导致工作无法正常开展。

那作为测试工程师,面对这样的情形,我们该怎么办呢?解决这类问题的核心的思路:引入依赖服务替身,更通俗的叫法,引入Mock服务。

今天就结合unittest框架,给大家分享一些关于Mock的一些常见使用。

2. Mock是什么

可能还有些读者之前并没有接触过Mock,不清楚Mock是个啥。

Mock简单来理解,就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试。而这个虚拟的对象就是mock对象。mock对象就是真实对象在调试期间的代替品。

有时也将Mock服务称之为测试服务替身,或者测试服务档板,下图很形象的描述了Mock的作用。

3. Mock能做什么

就Mock功能而言,本身适用场景较多,但在实际项目中,引入Mock常用来解决的几类,概括起来,主要有:

  • 接口间的相互依赖
  • 单元测试
  • 第三方接口调用

1.前后端联调

比如你是一个前端页面开发,现在需要开发一个功能:

下一个订单,支付页面的接口,根据支付结果,支付成功,展示支付成功页,支付失败,展示支付失败页。要完成此功能,你需要调用后端的接口,根据返回给你的结果,来展示不同的页面。此时后端接口还没开发好,作为一个前端开发总不能等别人开发好了,你再开发,那你只有加班的命了。为了同步开发完成任务,此时,你可以根据接口文档的规定,把接口的地址和入参传过去,然后自己mock接口的不同返回界面,来完成前端的开发任务。

2.单元测试

由于单元测试仅针对当前单元进行测试,这就要求所有的内部或者外部依赖都应该是稳定的,采用mock的方法模拟跟本单元依赖的其他单元,可以将测试重点放在当前单元功能,排除外界因素干扰,提升测试精准度。

3.第三方接口依赖

在做接口自动化的时候,有时候需要调用第三方的接口,但是别人公司的接口服务不受你的控制,有可能别人提供的测试环境今天服务给你开着,别人就关掉了,给自动化接口测试带来很多的麻烦,此时就可以通过mock来模拟接口的返回数据,比如模拟各种第三方异常时的返回。

4. Mock实现方式

Mock虽然是作为依赖服务的替身,但并不需要原原本本去构造实现一个完整的服务逻辑,比如现在有一个A服务依赖B服务,需要通过Mock来替换B服务(做一个假的B服务替身)。

那么我们做一个 Mock 服务其实就是做了一个简单的服务 B,它不需要实现原有服务 B 负载的处理逻辑,只要能按服务A需要服务B返回的处理逻辑给出对应返回数据就可以了。

目前常见服务或接口协议主要两种,一种是RPC,另一种是HTTP/HTTPS,mock原理都类似,要么是修改原服务地址为Mock服务地址,要么是拦截原服务的请求Mock返回值,总之就是构造一个假的服务,替代原有服务。

5. Mock市面上常见的解决方案

如果你不想自己动手构建一套Mock解决方案,市面上也提供了很多现存的Mock方案。

常用的有:EasyMockMockitoWireMockJMockitMockMoco

如果你团队技术基础相对比较薄弱,推荐你看看Moco这个方案,官网如下:

https://github.com/dreamhead/moco/

接下来,重点介绍Python系下Mock方案的使用。

6. Python下unittest.mock使用

unittest.mock是一个用于在Python中进行单元测试的库,顾名思义这个库的主要功能是模拟一些东西。它的主要功能是使用mock对象替代掉指定的Python对象,以达到模拟对象的行为。

需要注意的是在Python2.x版本中,Mock需要单独安装

pip install -U mock

从Python 3.3以后的版本mock已经合并到unittest模块中了,是unittest单元测试的一部分,直接导入过来就行

from unittest import mock

官方文档:

https://docs.python.org/dev/library/unittest.mock.html

unittest.mock模块中最常用的是Mock类。

Mock类库是一个专门用于在unittest过程中制作(伪造)和修改(篡改)测试对象的类库,避免这些对象在单元测试过程中依赖外部资源(网络资源,数据库连接,其它服务以及耗时过长等)

案例:

如下场景:支付是一个独立的接口,由其它开发提供,根据支付的接口返回状态去显示失败,还是成功,这个是你需要实现的功能,代码存放在pay.py脚本中:

# !/usr/bin/python3
# -*- coding: utf-8 -*-
# @Author : Mike Zhou
# @Email : 公众号:测试开发技术
# @File : pay.py def zhifu():
'''假设这里是一个支付的功能,未开发完
支付成功返回:{"result": "success", "msg":"支付成功"}
支付失败返回:{"result": "fail", "msg":"余额不足"}
'''
pass def zhifu_statues():
'''根据支付的结果success or fail,判断跳转到对应页面'''
result = zhifu()
try:
if result["result"] == "success":
return "支付成功"
elif result["result"] == "fail":
return "支付失败"
else:
return "未知错误异常"
except:
return "Error, 服务端返回异常!"

在zhifu_statues方法中,依赖了zhifu方法,但由于zhifu支付方法的接口是由另外一个同事开发,正常情况下,你同事开发的进度你是无法控制的,需要等他开发完了你才能进行联调你所负责的zhifu_statues接口,因此我们可以通过引入Mock来解决这个问题。

引入mock后单元测试用例代码

# !/usr/bin/python3
# -*- coding: utf-8 -*-
# @Author : Mike Zhou
# @Email : 公众号:测试开发技术 import unittest
from unittest import mock
import pay class TestZhifuStatues(unittest.TestCase):
'''单元测试用例'''
def test_01(self):
'''测试支付成功场景'''
# mock一个支付成功的数据
pay.zhifu = mock.Mock(return_value={"result": "success", "msg":"支付成功"})
# 根据支付结果测试页面跳转
statues = pay.zhifu_statues()
print(statues)
self.assertEqual(statues, "支付成功") def test_02(self):
'''测试支付失败场景'''
# mock一个支付失败的数据
pay.zhifu = mock.Mock(return_value={"result": "fail", "msg": "余额不足"})
# 根据支付结果测试页面跳转
statues = pay.zhifu_statues()
print(statues)
self.assertEqual(statues, "支付失败") if __name__ == "__main__":
unittest.main()

上述代码引入Mock后,我们就可以顺利完成对支付成功和支付异常两类场景的验证工作。(实际你可以补充更多)

mock中还有另一种实现方式,通过patch装饰器的使用,patch作为函数装饰器,为您创建模拟并将其传递到装饰函数。

用mock.patch实现如下:

# !/usr/bin/python3
# -*- coding: utf-8 -*-
# @Author : Mike Zhou
# @Email : 公众号:测试开发技术 import unittest
from unittest import mock
import pay class TestZhifuStatues(unittest.TestCase):
'''单元测试用例''' @mock.patch("pay.zhifu")
def test_001(self, mock_zhifu):
'''测试支付成功场景'''
# 方法一:mock一个支付成功的数据
# pay.zhifu = mock.Mock(return_value={"result": "success", "msg":"支付成功"})
# print(pay.zhifu()) # 方法二:mock.path装饰器模拟返回结果
mock_zhifu.return_value = {"result": "success", "msg":"支付成功"} # # 根据支付结果测试页面跳转
statues = pay.zhifu_statues()
print(statues)
self.assertEqual(statues, "支付成功") @mock.patch("pay.zhifu")
def test_002(self, mock_zhifu):
'''测试支付失败场景'''
# mock一个支付失败的数据 mock_zhifu.return_value = {"result": "fail", "msg": "余额不足"}
# 根据支付结果测试页面跳转
statues = pay.zhifu_statues()
self.assertEqual(statues, "支付失败") if __name__ == "__main__":
unittest.main()

测试开发工程必备技能之一:Mock的使用的更多相关文章

  1. 【转】测试开发工程师必备软硬能力&高级测试开发工程师需要具备什么能力?

    对于测试的基本知识,可以查看软件测试相关书籍 对于在公司成为一位优秀的测试开发工程师,我觉得下面这篇文章涉及到的是我们需要的,稍微进行改动https://blog.csdn.net/sinat_210 ...

  2. 学好三角学(函数) — SWIFT和JAVASCRIPT游戏开发的必备技能 iFIERO.com

    不论是使用哪种平台进行开发,三角学在游戏当中都被广泛的使用,因此,小编iFERO认为,三角学是必须得掌握的技能之一. 游戏图片由 摘自 Razeware LLC 先以Javascript为例 一.角度 ...

  3. GDB调试:Linux开发人员必备技能

    开篇词:Linux C/C++ 开发人员要熟练掌握 GDB 调试 大家好,我是范蠡,目前在某知名互联网旅游公司基础框架业务部技术专家组任开发经理一职. 本系列课程的主题是 Linux 后台开发的 C/ ...

  4. iOS开发工程师必备技能(持续更新)

    Objective-C Objective-C语言基础 library,framework的制作 Runtime 编程 LLVM 原理和调优 操作系统 iOS内存管理和调优 iOS的文件系统和沙盒机制 ...

  5. [转帖]java必备的开发知识和技能

    java必备的开发知识和技能 https://blog.csdn.net/qq_34405062/article/details/89389646 学习一下java 其实上学那会儿学的 早就过时加落伍 ...

  6. Fiddler无所不能——之测试开发攻城狮必备利器

    Fiddler无所不能——之测试开发攻城狮必备利器 1.模拟真实网络环境4g网.3g网络.2g网络.弱网.请求超时 开启弱网Rules——Performance——勾选Simulate Modem S ...

  7. 测试开发【Mock平台】04实战:前后端项目初始化与登录鉴权实现

    [Mock平台]为系列测试开发教程,从0到1编码带你一步步使用Spring Boot 和 Antd React 框架完成搭建一个测试工具平台,希望作为一个实战项目能为你的测试开发学习有帮助. 一.后端 ...

  8. 【Mock平台】测试开发实战01-开篇PRD和需求详细

    微信搜索[大奇测试开],关注这个坚持分享测试开发干货的家伙. 平台背景 从业务特性上,不少测试的服务很多是依赖第三方的接口的,比如其中的支付场景,就需要很多状态的返回进行验证,但大部分服务提供商没有很 ...

  9. 百度Hr分享,一个合格的数据工程师简历中必备技能?

    如果你是一名数据科学方面的求职者,你肯定想知道在简历上写些什么才能获得面试的机会:如果你想进入这个领域,你一定想知道具备哪些技术才能成为一名有竞争力的求职者. 在本文中,我们对Indeed中一千份数据 ...

随机推荐

  1. [Luogu P4215] 踩气球 (线段树)

    题面 传送门:https://www.luogu.org/problemnew/show/P4215 Solution 这题十分有意思. 首先,我们可以先想想离线做法,因为在线做法可以从离线做法推出. ...

  2. 洛谷 P2391 白雪皑皑 线段树+优化

    题目描述: 现在有 \(N\) 片雪花排成一列. Pty 要对雪花进行$ M $次染色操作,第 \(i\)次染色操作中,把\((i*p+q)%N+1\) 片雪花和第\((i*q+p)%N+1\)片雪花 ...

  3. Docker(7)- docker images 命令详解

    如果你还想从头学起 Docker,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1870863.html 作用 列出所有的本地镜像 语法格 ...

  4. 关于||和&&运算符及表达式的执行

    ++a || ++b && ++c表达式中++a,--b,++c三者执行与否的判断 在||运算符前的表达式为真,则其后的表达式不执行 eg:执行前 a=2,  b=2,  c=2 执行 ...

  5. c#导入文件

    string[] lines = System.IO.File.ReadAllLines(@"C:\Users\Administrator\Desktop\2.txt",Encod ...

  6. 18、Celery

    Celery 1.什么是Clelery Celery是一个简单.灵活且可靠的,处理大量消息的分布式系统 专注于实时处理的异步任务队列 同时也支持任务调度 Celery架构 Celery的架构由三部分组 ...

  7. Java实现FTP跨服务器文件操作

    在过去的几年工作中,曾经多次需要把文件上传到单独的服务器,而程序是在单独的服务器上部署的,在进行文件操作的时候就需要跨服务器进行操作包括:文件上传.文件下载.文件删除等.跨服务器文件操作一般是需要FT ...

  8. [C/C++]详解结构体

    引子 设计程序时,最重要的步骤之一就是选择表示数据的方法.在许多情况下,简单变量甚至是数组还不够.为此,C提供了结构变量(structure variable)提高表示数据的能力,它能够创造新的形式. ...

  9. Linux(CentOS6.8)配置ActiveMQ

    1.下载ActiveMQ http://activemq.apache.org/ 注:若是想下载老版本的ActiveMQ可以通过以下链接下载 http://activemq.apache.org/do ...

  10. 直面秋招!非科班生背水一战,最终拿下阿里等大厂offer!

    前言 2020年已经接近到9月份了,很多粉丝朋友都对金九银十雀雀欲试了吧!也有很多朋友向我求教经验,因为我自己工作相对于稳定,在这里给大家分享一个粉丝朋友的经历,他作为一个曾经的菜鸡面试者,在不断的失 ...