接口自动化测试mock框架模块实战

news2024/12/28 9:18:03
前言

mock的介绍

py3已将mock集成到unittest库中;
为的就是更好的进行单元测试;
简单理解,模拟接口返回参数;
通俗易懂,直接修改接口返回参数的值;

mock的作用

1、解决依赖问题,达到解耦作用
当我们测试某个目标接口(模块)时,该接口依赖其他接口,当被依赖的接口未开发完成时,可以用mock模拟被依赖接口,完成目标接口的测试;

2、模拟复杂业务的接口
当我们测试某个目标接口(模块),该接口依赖一个非常复杂的接口时,可以用mock来模拟这个复杂的业务接口;也解决接口依赖一样的原理

3、单元测试
如果某个接口(模块)未开发完成时,又需要编写测试用例,则可以通过mock模拟该接口(模块)进行测试

4、前后端联调
前端开发的页面需要根据后端返回的不同状态码展示不同的页面,当后端接口未开发完成时,也可通过mock来模拟后端接口返回自己想要的数据

mock类解读

  1. class Mock(spec=None,side_effect=None,return_value=DEFFAULT,name=None)

secp:定义mock对象的属性值,可以是列表,字符串,甚至一个对象或者实例
side_effect:可以用来抛出异常或者动态改变返回值,它必须是一个iterator(列表),它会覆盖return_value
return_value:定义mock方法的返回值,它可以是一个值,可以是一个对象(如果存在side_effect参数那这个就没有用,也就是不能同时用)
name:作为mock对象的一个标识,在print时可以看到

mock实际使用

一个未开发完成的功能如何测试?


def add(self, a, b):

"""两个数相加"""

pass



class TestSub(unittest.TestCase):

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


def test_sub(self):

# 创建一个mock对象 return_value代表mock一个数据

mock_add = mock.Mock(return_value=15)

# 将mock对象赋予给被测函数

add = mock_add

# 调用被测函数

result = add(5, 5)

# 断言实际结果和预期结果

self.assertEqual(result, 15)

一个完成开发的功能如何测试?


class SubClass(object):

def add(self, a, b):

"""两个数相加"""

return a + b



class TestSub(unittest.TestCase):

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



def test_add2(self):

# 初始化被测函数类实例

sub = SubClass()

# 创建一个mock对象 return_value代表mock一个数据

# 传递side_effect关键字参数, 会覆盖return_value参数值, 使用真实的add方法测试

sub.add = Mock(return_value=15, side_effect=sub.add)

# 调用被测函数

result = sub.add(5, 5)

# 断言实际结果和预期结果

self.assertEqual(result, 10)

side_effect:这里给的参数值是sub.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):

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

print(mock_obj())

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

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


# 支付类

class Payment:


def requestOutofSystem(self, card_num, amount):

'''

请求第三方外部支付接口,并返回响应码

:param card_num: 卡号

:param amount: 支付金额

:return: 返回状态码,200 代表支付成功,500 代表支付异常失败

'''

# 第三方支付接口请求地址(故意写错)

url = "http://third.payment.pay/"

# 请求参数

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

response = requests.post(url, data=data)

# 返回状态码

return response.status_code


def doPay(self, user_id, card_num, amount):

'''

支付

:param userId: 用户ID

:param card_num: 卡号

:param amount: 支付金额

:return:

'''

try:

# 调用第三方支付接口请求进行真实扣款

resp = self.requestOutofSystem(card_num, amount)

print('调用第三方支付接口返回结果:', resp)

except TimeoutError:

# 如果超时就重新调用一次

print('重试一次')

resp = self.requestOutofSystem(card_num, amount)


if resp == 200:

# 返回第三方支付成功,则进行系统里面的扣款并记录支付记录等操作

print("{0}支付{1}成功!!!进行扣款并记录支付记录".format(user_id, amount))

return 'success'


elif resp == 500:

# 返回第三方支付失败,则不进行扣款

print("{0}支付{1}失败!!不进行扣款!!!".format(user_id, amount))

return 'fail'


# 单元测试类

class payTest(unittest.TestCase):


def test_pay_success(self):

pay = Payment()

# 模拟第三方支付接口返回200

pay.requestOutofSystem = mock.Mock(return_value=200)

resp = pay.doPay(user_id=1, card_num='12345678', amount=100)

self.assertEqual('success', resp)


def test_pay_fail(self):

pay = Payment()

# 模拟第三方支付接口返回500

pay.requestOutofSystem = mock.Mock(return_value=500)

resp = pay.doPay(user_id=1, card_num='12345678', amount=100)

self.assertEqual('fail', resp)


def test_pay_time_success(self):

pay = Payment()

# 模拟第三方支付接口首次支付超时,重试第二次成功

pay.requestOutofSystem = mock.Mock(side_effect=[TimeoutError, 200])

resp = pay.doPay(user_id=1, card_num='12345678', amount=100)

self.assertEqual('success', resp)


def test_pay_time_fail(self):

pay = Payment()

# 模拟第三方支付接口首次支付超时,重试第二次失败

pay.requestOutofSystem = mock.Mock(side_effect=[TimeoutError, 500])

resp = pay.doPay(user_id=1, card_num='12345678', amount=100)

self.assertEqual('fail', resp)

可能会有人问:第三方支付都不能用,我们的测试结果是否是有效的呢?

通常在测试一个模块的时候,是可以认为其他模块的功能是正常的,只针对目标模块进行测试是没有任何问题的,所以说测试结果也是正确的

mock装饰器

一共两种格式


@patch('module名字.方法名')

@patch.object(类名, '方法名')

# 装饰类演示

from mock import Mock, patch



# 单独的相乘函数

def multiple(a, b):

return a * b



# 单独的捕获Exception函数

def is_error():

try:

os.mkdir("11")

return False

except Exception as e:

return True



# 计算类,包含add方法

class calculator(object):

def add(self, a, b):

return a + b



# 装饰类演示 - 单元测试类

class TestProducer(unittest.TestCase):


# case执行前

def setUp(self):

self.calculator = calculator()


# mock一个函数,注意也要指定module

@patch('mock_learn.multiple')

def test_multiple(self, mock_multiple):

mock_multiple.return_value = 3

self.assertEqual(multiple(8, 14), 3)


# mock一个类对象的方法

@patch.object(calculator, 'add')

def test_add(self, mock_add):

mock_add.return_value = 3

self.assertEqual(self.calculator.add(8, 14), 3)


# mock调用方法返回多个不同的值

@patch.object(calculator, 'add')

def test_effect(self, mock_add):

mock_add.side_effect = [1, 2, 3]

self.assertEqual(self.calculator.add(8, 14), 1)

self.assertEqual(self.calculator.add(8, 14), 2)

self.assertEqual(self.calculator.add(8, 14), 3)


# mock的函数抛出Exception

@patch('os.mkdir')

def test_exception(self, mkdir):

mkdir.side_effect = Exception

self.assertEqual(is_error(), True)


# mock多个函数,注意函数调用顺序

@patch.object(calculator, 'add')

@patch('mock_learn.multiple')

def test_more(self, mock_multiple, mock_add):

mock_add.return_value = 1

mock_multiple.return_value = 4

self.assertEqual(self.calculator.add(3, 3), 1)

self.assertEqual(multiple(3, 3), 4)

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1983495.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于Spring前后端分离版本的论坛

基于Spring前后端分离版本的论坛系统 PP论坛地址系统设计逻辑交互图数据库设计工程结构概述注册功能实现展示注册交互图参数要求接口规范后端具体实现前端数据集成 接口拦截器实现mybatis生成类与映射文件改造session存储到 redis加盐算法实现部分Bug调试记录项目测试记录Postm…

关于正点原子imx6ull-mini在写触摸驱动时,一直挂载不上驱动,就是没有一些信息反馈

/** 设备树匹配表 */ const struct of_device_id gt9147_of_match_table[] {{.compatible "goodix,gt9147" },{ /* sentinel */ } };const struct of_device_id gt9147_of_match_table[] {{.compatible "goodix&#xff0c;gt9147"},{} }; 找了俩小时…

高频面试题全攻略:从算法到解题技巧

干货分享&#xff0c;感谢您的阅读&#xff01; &#xff08;暂存篇---后续会删除&#xff0c;完整版和持续更新见高频面试题基本总结回顾&#xff08;含笔试高频算法整理&#xff09;&#xff09; 备注&#xff1a;引用请标注出处&#xff0c;同时存在的问题请在相关博客留言…

基于宝塔面板稳定快速安装 ssl 证书脚本

背景 我通过AI制作了不少关于签发ssl证书的脚本&#xff0c;目的是方便无脑安装&#xff0c;不需要懂代码。 但全都是基于acme.sh这个工具来设计的脚本&#xff0c;而且证书申请有点慢&#xff0c;有时还会申请失败。 然后我发现了certbot, 安装证书可谓神速&#xff01; c…

[米联客-安路飞龙DR1-FPSOC] UDP通信篇连载-04 IP层程序设计

软件版本&#xff1a;Anlogic -TD5.9.1-DR1_ES1.1 操作系统&#xff1a;WIN10 64bit 硬件平台&#xff1a;适用安路(Anlogic)FPGA 实验平台&#xff1a;米联客-MLK-L1-CZ06-DR1M90G开发板 板卡获取平台&#xff1a;https://milianke.tmall.com/ 登录“米联客”FPGA社区 ht…

全面解析PHP反序列化漏洞:原理、复现与防御

文章目录 概念序列化数据的含义魔术方法魔术方法的使用construct&#xff0c;destructtoStringcallgetsetsleepwakeupissetunsetinvoke 原生态反序列化漏洞概念种类复现 wakeup长度绕过产生原因条件复现 基本题型源码解读 在Web应用安全领域&#xff0c;PHP反序列化漏洞常常被视…

Tomcat 使用和配置文件(详解)

一.tomcat 介绍 1. tomcat 概述 自从JSP发布之后&#xff0c;推出了各式各样的JSP引擎。Apache Group在完成GNUJSP1.0的开发以后&#xff0c;开始考虑在SUN的JSWDK基础上开发一个可以直接提供Web服务的JSP服务器&#xff0c;当然同时也支持 Servlet&#xff0c;这样Tomcat就诞…

MySQL数据库误删恢复--超详细

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…

Tensorflow——第三讲神经网络八股

前两讲我们学习了使用tensorflow原生代码搭建神经网络&#xff0c;本讲主要学习使用Tensorflow API&#xff1a;tf.keras搭建神经网络 一、搭建网络八股Sequential 六步法&#xff1a; 1.import&#xff1a;import 相关模块&#xff0c;如 import tensorflow as tf 2.train…

2024年7月30日~2024年8月5日周报

一、前言 上周继续修改论文&#xff0c;并阅读了两篇论文。 本周主要修改论文、完成实验、参加一些组会与论文讨论会&#xff0c;并配置了torch环境。 二、完成情况 2.1 论文符号系统注意事项 数学符号应该有唯一性&#xff0c;不能与其他符号造成误解&#xff1b;W_{\mathr…

c++初阶-----适配器---priority_queue

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

极狐GitLab CICD Catalog Beta 功能介绍

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门面向中国程序员和企业提供企业级一体化 DevOps 平台&#xff0c;用来帮助用户实现需求管理、源代码托管、CI/CD、安全合规&#xff0c;而且所有的操作都是在一个平台上进行&#xff0c;省事省心省钱。可以一键安装极狐GitL…

【Python】数据类型之列表(下)

&#xff08;6&#xff09;清空列表 功能&#xff1a;clear() 代码示例&#xff1a; &#xff08;7&#xff09;根据值获取索引&#xff08;从左到右找到第一个返回索引&#xff09;【慎用&#xff0c;找不到报错】 功能&#xff1a;index(xyz)&#xff0c;xyz为数据类型。 …

OpenAI gym player mode

题意&#xff1a;OpenAI gym 的自定义模式 问题背景&#xff1a; Does anyone know how to run one of the OpenAI gym environments as a player. As in letting a human player play a round of cart pole? I have seen that there is env.mode human but I have not been…

波兰表达式求值

from operator import add, sub, muldef div(x, y):# 使用整数除法的向零取整方式return int(x / y) if x * y > 0 else -(abs(x) // abs(y))class Solution(object):op_map {: add, -: sub, *: mul, /: div}def evalRPN(self, tokens: List[str]) -> int:stack []for …

【C基础-按要求找数】一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少

一个整数&#xff0c;它加上100后是一个完全平方数&#xff0c;再加上168又是一个完全平方数&#xff0c;请问该数是多少 完全平方数是指一个整数能够表示为某个整数的平方。换句话说&#xff0c;如果存在一个整数 n&#xff0c;使得 n^2m,那么 m 就是一个完全平方数。 使用C…

第二十一天培训笔记

上午 1 、环境准备 2 、安装 mysql 绿包 3 、配置 mysql 工作环境 mysql -hip 地址 -p3306 -uroot -p &#xff08;远程连接使用&#xff09; 4 、 mysql 基础命令 &#xff08; 1 &#xff09;修改密码 &#xff08; 2 &#xff09;授权远程登录 &#xff08; 3 &#x…

程序员短视频上瘾综合症

一、是你疯了还是面试官疯了&#xff1f; ​ 最近有两个学员咨询问题&#xff0c;把我给整得苦笑不得。大家来看看&#xff0c;你有没有同样的症状。 ​ 第一个学员说去一家公司面试&#xff0c;第一轮面试聊得挺好的。第二轮面试自我感觉良好&#xff0c;但是被面试官给Diss…

模型优化学习笔记—对比各种梯度下降算法

import mathimport numpy as np from opt_utils import * import matplotlib.pyplot as plt# 标准梯度下降 def update_parameters_with_gd(parameters, grads, learning_rate):L len(parameters) // 2for l in range(1, L 1):parameters[f"W{l}"] parameters[f&q…

【uniapp】聊天记录列表长按消息计算弹出菜单方向

1. 效果图 1.1 消息靠上接近导航栏&#xff0c;菜单显在消息体下方弹出&#xff0c;箭头向上 1.2 消息体没有贴近上方导航栏&#xff0c;菜单在消息体上方弹出&#xff0c;箭头向下 1.3 长消息&#xff0c;菜单在手指按下的位置弹出&#xff0c;无箭头 2. 代码实现 <view …