mock简介

mock原是python的第三方库,python 2可以直接安装mock模块,但在python 3.3以后mock模块已经整合到了unittest测试框架中,不需要再单独安装。

Mock这个词在英语中有模拟的这个意思,因此我们可以猜测出这个库的主要功能是模拟一些东西。准确的说,Mock是Python中一个用于支持单元测试的库,它的主要功能是使用mock对象替代掉指定的Python对象,以达到模拟对象的行为。简单的说,mock库用于如下的场景:假设你开发的一个api在工作的时候需要调用发送请求给特定的服务器来得到一个JSON返回值,然后根据这个返回值来做处理。如果要为该API写一个单元测试,该如何做?

一个简单的办法是搭建一个测试的服务器,在单元测试的时候,让该API和这个测试服务器交互。但是这种做法有两个问题:

1、测试服务器可能很不好搭建,或者搭建效率很低。

2、你搭建的测试服务器可能无法返回所有可能的值,或者需要大量的工作才能达到这个目的。

那么如何在没有测试服务器的情况下进行上面这种情况的单元测试呢?Mock模块就是答案。因为mock模块可以替换Python对象,返回值能够由我们的mock对象来决定,而不需要服务器的参与。

mock作用:

1. 解决依赖问题:当我们测试一个接口或者功能模块的时候,如果这个接口或者功能模块依赖其他接口或其他模块,那么如果所依赖的接口或功能模块未开发完毕,那么我们就可以使用mock模拟被依赖接口,完成目标接口的测试

2. 单元测试:如果某个功能未开发完成,我们又要进行测试用例的代码编写,我们也可以先模拟这个功能进行测试

3. 模拟复杂业务的接口:实际工作中如果我们在测试一个接口功能时,如果这个接口依赖一个非常复杂的接口业务,那么我们完全可以使用mock来模拟这个复杂的业务接口,其实这个和解决接口依赖是一样的原理

4.前后端联调:如果你是一个前端页面开发,现在需要开发一个功能:根据后台返回的状态展示不同的页面,那么你就需要调用后台的接口,但是后台接口还未开发完成,是不是你就停止这部分工作呢?答案是否定的,你完全可以借助mock来模拟后台这个接口返回你想要的数据

Mock的安装和导入

1、在Python 3.3以前的版本中,需要另外安装mock模块,可以使用pip命令来安装:pip install mock

然后在代码中就可以直接import进来:import mock

2、从Python 3.3开始,mock模块已经被合并到标准库中,被命名为unittest.mock,可以直接import进来使用:from unittest import mock

Mock对象

Mock对象是mock模块中最重要的概念。Mock对象就是mock模块中的一个类的实例,这个类的实例可以用来替换其他的Python对象,来达到模拟的效果。Mock类的定义如下:classMock(spec=None, side_effect=None, return_value=DEFAULT, wraps=None, name=None, spec_set=None, **kwargs)

Mock对象的一般用法是这样的:

1、找到你要替换的对象,这个对象可以是一个类,或者是一个函数,或者是一个类实例。

2、然后实例化Mock类得到一个mock对象,并且设置这个mock对象的行为,比如被调用的时候返回什么值,被访问成员的时候返回什么值等。

3、使用这个mock对象替换掉我们想替换的对象,也就是步骤1中确定的对象。

4、之后就可以开始写测试代码,这个时候我们可以保证我们替换掉的对象在测试用例执行的过程中行为和我们预设的一样。

mock实例及基本用法

一个未开发完成的功能如何测试?假如们现在有一个实现两个数相加的功能需要编写测试用例,但是由于开发进度缓慢,只搭两个简单的框架,并没有内部实现。import unittest

from unittest import mock

class SubClass(object):

def add(self, a, b):

"""两个数相加"""

pass

class TestSub(unittest.TestCase):

"""测试两个数相加用例"""

def test_sub(self):

sub = SubClass()  # 初始化被测函数类实例

sub.add = mock.Mock(return_value=10)  # mock add方法 返回10

result = sub.add(5, 5)  # 调用被测函数

self.assertEqual(result, 10)  # 断言实际结果和预期结果

if __name__ == '__main__':

unittest.main()

测试结果:----------------------------------------------------------------------

Ran 1 test in 0.000s

OK

Process finished with exit code

测试结果显示,测试用例执行通过了。

实际上mock模拟add方法的原理是 使用相同的对象方法接收mock的对象(使用sub.add接收),那么当mock对象被调用时(sub.add())就会返回return_value参数对应的数据

稍微高级的用法

1、class Mock的参数

上面讲的是mock对象最基本的用法。下面来看看mock对象的稍微高级点的用法

先来看看Mock这个类的参数,在上面看到的类定义中,我们知道它有好几个参数,这里介绍最主要的几个:

name: 这个是用来命名一个mock对象,只是起到标识作用,当你print一个mock对象的时候,可以看到它的name。

return_value: 这个我们刚才使用过了,这个字段可以指定一个值(或者对象),当mock对象被调用时,如果side_effect函数返回的是DEFAULT,则对mock对象的调用会返回return_value指定的值。

side_effect: 这个参数指向一个可调用对象,一般就是函数。当mock对象被调用时,如果该函数返回值不是DEFAULT时,那么以该函数的返回值作为mock对象调用的返回值。

上面的例子,我们把用例的代码修改一句如下:class TestSub(unittest.TestCase):

"""测试两个数相加"""

def test_sub(self):

sub = SubClass()  # 初始化被测函数类实例

sub.add = mock.Mock(return_value=10, side_effect=sub.add)  # 传递side_effect关键字参数, 会覆盖return_value参数值, 使用真实的add方法测试

result = sub.add(5, 11)  # 真正的调用被测函数

self.assertEqual(result, 16)  # 断言实际结果和预期结果

代码中我们给Mock方法添加了另一个关键字参数side_effect = sub.add, 这个参数和return_value 正好相反,当传递这个参数的时候return_value 参数就会失效

而side_effect生效,这里我给的参数值是sub.add 相当于add方法的地址,那么当调用add方法时就会真实的使用add方法,也就达到了我们测试实际的add 方法。

你也可以理解为当传递了side_effect参数且值为被测方法地址时,mock就不会起作用

side_effect接收的是一个可迭代序列,当传递多个值时,那么每次调用mock时会返回不同的值mock_obj = mock.Mock(side_effect= [1,2,3])

print(mock_obj())

print(mock_obj())

print(mock_obj())

print(mock_obj())

输出

Traceback (most recent call last):

1

File "D:/MyThreading/mymock.py", line 37, in

2

print(mock_obj())

3

File "C:\Python36\lib\unittest\mock.py", line 939, in __call__

return _mock_self._mock_call(*args, **kwargs)

File "C:\Python36\lib\unittest\mock.py", line 998, in _mock_call

result = next(effect)

StopIteration

Process finished with exit code 1

当所有值被取完后就会报错(这个地方有点类似生成器的原理)

2、mock对象的自动创建

当访问一个mock对象中不存在的属性时,mock会自动建立一个子mock对象,并且把正在访问的属性指向它,这个功能对于实现多级属性的mock很方便。

client= mock.Mock()client.v2_client.get.return_value ='200'

这个时候,你就得到了一个mock过的client实例,调用该实例的v2_client.get()方法会得到的返回值是"200"。

从上面的例子中还可以看到,指定mock对象的return_value还可以使用属性赋值的方法。

存在依赖关系的功能如何测试?

假设有这样一个场景:我们要测试一个支付接口但是这个支付接口又依赖一个第三方支付接口,那么第三方支付接口我们暂时没有权限使用,那么我们该如何测试我们自己这个接口呢?

看下面的实例,假设第三方接口和我们自己的支付接口如下:import requests

class PayApi(object):

@staticmethod

def auth(card, amount):

"""

第三方支付接口

:param card: 卡号

:param amount: 支付金额

:return:

"""

pay_url = "http://www.zhifubao.com"  # 第三方支付接口地址

data = {"card": card, "amount": amount}

response = requests.post(pay_url, data=data)  # 请求第三方支付接口

return response  # 返回状态码

def pay(self, user_id, card, amount):

"""

我们自己的支付接口

:param user_id: 用户id

:param card: 卡号

:param amount: 支付金额

:return:

"""

# 调用第三方支付接口

response = self.auth(card, amount)

try:

if response['status_code'] == '200':

print('用户{}支付金额{}成功'.format(user_id, amount))

return '支付成功'

elif response['status_code'] == '500':

print('用户{}支付失败, 金额不变'.format(user_id))

return '支付失败'

else:

return '未知错误'

except Exception:

return "Error, 服务器异常!"

if __name__ == '__main__':

pass

很明显第三方支付接口是无法访问的,因为接口的地址是我DIY的,为了模拟实际中我们无法使用的第三方支付接口。编写测试用例如下:import unittest

from unittest import mock

from payment.PayMent import PayApi

class TestPayApi(unittest.TestCase):

def test_success(self):

pay = PayApi()

pay.auth = mock.Mock(return_value={'status_code':'200'})

status = pay.pay('1000', '12345', '10000')

self.assertEqual(status, '支付成功')

def test_fail(self):

pay = PayApi()

pay.auth = mock.Mock(return_value={'status_code':'500'})

status = pay.pay('1000', '12345', '10000')

self.assertEqual(status, '支付失败')

def test_error(self):

pay = PayApi()

pay.auth = mock.Mock(return_value={'status_code':'300'})

status = pay.pay('1000', '12345', '10000')

self.assertEqual(status, '未知错误')

def test_exception(self):

pay = PayApi()

pay.auth = mock.Mock(return_value='200')

status = pay.pay('1000', '12345', '10000')

self.assertEqual(status, 'Error, 服务器异常!')

if __name__ == '__main__':

unittest.main()

测试输出结果:....用户1000支付失败, 金额不变

用户1000支付金额10000成功

----------------------------------------------------------------------

Ran 4 tests in 0.001s

OK

Process finished with exit code 0

从执行结果可以看出,即使第三方支付接口无法使用,但是我们自己的支付接口仍然测试通过了。也许有人会问,第三方支付都不能用,我们的测试结果是否是有效的呢?通常我们在测试一个模块的时候,我们是可以认为其他模块的功能是正常的,只针对目标模块进行测试是没有任何问题的,所以说测试结果也是正确的。

python接口自动化接口依赖_Python接口自动化之mock模块简单使用相关推荐

  1. python接口自动化测试面试题_Python 接口自动化测试实战

    Python接口自动化测试实战 简介 本课程主要围绕Python相关库再服务端接口自动化测试中的应用展开介绍,重点讲解接口自动化基础.编写接口自动化脚本.框架原理.项目实战,此外还扩展介绍多用例管理与 ...

  2. python接口编程的好处_python接口自动化测试

    mock简介 py3已将mock集成到unittest库中 为的就是更好的进行单元测试 简单理解,模拟接口返回参数 通俗易懂,直接修改接口返回参数的值 mock作用 解决依赖问题,达到解耦作用 当我们 ...

  3. python做接口自动化测试仪器经销商_Python接口自动化测试的实现

    接口测试的方式有很多,比如可以用工具(jmeter,postman)之类,也可以自己写代码进行接口测试,工具的使用相对来说都比较简单,重点是要搞清楚项目接口的协议是什么,然后有针对性的进行选择,甚至当 ...

  4. python接口自动化关联参数_python接口自动化7-参数关联

    前言 我们用自动化发帖之后,要想接着对这篇帖子操作,那就需要用参数关联了,发帖之后会有一个帖子的id,获取到这个id,继续操作传这个帖子id就可以了 (博客园的登录机制已经变了,不能用账号和密码登录了 ...

  5. python接口自动化实战(框架)_python接口自动化框架实战

    python接口测试的原理,就不解释了,百度一大堆. 先看目录,可能这个框架比较简单,但是麻雀虽小五脏俱全. 各个文件夹下的文件如下: 一.理清思路 我这个自动化框架要实现什么 1.从excel里面提 ...

  6. python接口自动化pdf悠悠_python接口自动化13-data和json参数傻傻分不清【悠悠】

    https://www.cnblogs.com/yoyoketang/p/7231384.html 前言 在发post请求的时候,有时候body部分要传data参数,有时候body部分又要传json参 ...

  7. python绕过付费认正_python接口自动化三(登录绕开验证码及发帖)

    前言 有些登录的接口会有验证码:短信验证码,图形验证码等,这种登录的话验证码参数可以从后台获取的(或者查数据库最直接). 获取不到也没关系,可以通过添加cookie的方式绕过验证码. 但是这里需要明确 ...

  8. python中sign函数图片_python接口自动化-实现sign签名(MD5加密)

    一,前序 今天在学习sign签名的的时候,了解了下常用的sign加密算法,突然心血来潮,想用python试着将签名生成的通用步骤用代码实现出来,虽然中间经历了一点小波折,请教了开发同事后,按照他给的思 ...

  9. python 自动上报json信息_python接口自动化5-Json数据处理

    前言 有些post的请求参数是json格式的,这个前面第二篇post请求里面提到过,需要导入json模块处理. 一般常见的接口返回数据也是json格式的,我们在做判断时候,往往只需要提取其中几个关键的 ...

最新文章

  1. android 展开式按钮,Android自定义View实现可展开、会呼吸的按钮
  2. Java Lambda表达式forEach无法跳出循环的解决思路
  3. js中表单验证常用到的正则表达式
  4. boost::mp11::mp_find_if_q相关用法的测试程序
  5. spring boot在运行测试类Error creating bean with name ‘serverEndpointExporter‘ defined...问题解决方案
  6. Selenium 中文API
  7. asp.net core使用serilog将日志推送到腾讯云日志服务
  8. ActiveRecord学习笔记(四):处理Many-To-Many映射
  9. 【数据结构】顺序线性表的几种常用方法
  10. windows11,安装maven。
  11. 如何使用鲁大师进行驱动备份
  12. win+ubuntu双系统卸载ubuntu
  13. 汇智网mysql_MySQL 入门
  14. 无线ap安全dhcp服务器,AC+AP时代——办公区内满足安全性又够人性化的WiFi漫游设置攻略...
  15. 设计模式之 Vistor 访问者模式:Swift 实现
  16. 【Python】图片视频处理常用操作及方法
  17. 教室计算机广播控制,小学智能广播系统(模拟广播)系统解决方案
  18. 阿里云搭建 samba服务器
  19. oracle 把结果加上百分号_用一条sql语句显示数据百分比并加百分号
  20. 【转】很好的英文自我介绍

热门文章

  1. hexo不渲染html文件,解决hexo渲染的页面中有br的问题
  2. python实现rsa加密源代码_python实现RSA加密(解密)算法
  3. 45页的NAS神经网络搜索的综述,请查收!
  4. 十万条评论告诉你,给《流浪地球》评1星的都是什么心态?
  5. c语言用什么能暂存结构指针,c语言中什么是指针
  6. cocos2d python文档_【Cocos2D-X 学习笔记】Cocos2D-x 3.0+VS开发环境搭建[使用Python]
  7. 为什么下拉框拉不下来_零线不带电,为什么还要拉一条?直接用地做零线不是更省钱?...
  8. 徐州计算机财务管理课程实验,《计算机财务管理实验报告》.docx
  9. 计算机的桌面图片还原,电脑桌面图标重启后自动复原的解决方法。
  10. XGBoost使用教程(与sklearn一起使用)二