百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

Python 中 Mock 到底该怎么玩?一篇文章告诉你

off999 2024-12-27 15:59 21 浏览 0 评论

来源:AirPython

作者:星安果

1. 前言

微服务架构下,由于各类服务开发进度的不一致,导致联调工作经常会存在不确定性,进而导致项目延期

在实际工作中,为了保证项目进度,我们经常需要针对部分未完成模块及不稳定模块采用 Mock 方式,以验证已开发完的模块

本篇文章将介绍 Python 实现 Mock 的几种常见方式

2. Mock 介绍

Mock 测试:在测试验证过程中,对于那些尚未完成或不稳定的对象,用一个虚拟对象来替代,以便测试的测试方法

因此,这个虚拟的对象是 Mock 对象,Mock 对象是真实对象在调试期间的代替品

它的优势包含:

  • 前、后端并行开发
  • 模拟无法访问的资源
  • 隔离系统,避免脏数据干扰测试结果
  • 3.1 mock

    在 Python 3.3 之前使用 mock,需要先安装依赖

    # 安装mock依赖
    pip3 install mock

    假设 Product 类中有 2 个方法

  • get_product_status_by_id
  • buy_product
  • 其中,get_product_status_by_id 方法还没有实现;buy_product 方法依赖于 get_product_status_by_id 方法的返回值

    # product_impl.py
    class Product(object):
    def __init__(self):
    pass
    def get_product_status_by_id(self, product_id):
    """
    通过商品id获取产品信息(Mock)
    :return:
    """

    # 待实现查询数据库的业务逻辑
    pass
    def buy_product(self, product_id):
    """
    购买产品(真实逻辑)
    :return:
    """

    # 产品信息
    # {"id":1,"name":"苹果","num":23}
    product = self.get_product_status_by_id(product_id)
    if product.get("num") >= 1:
    result = {
    "status": 0, "msg": "购买成功!"}
    else:
    result = {
    "status": 1, "msg": "购买失败,库存不足!"}
    return result

    Mock 的步骤如下:
    导入使用 mock 中的 patch 方法作为测试方法的装饰器,对 get_product_status_by_id 方法进行 Mock,方法参数为 Mock 对象测试方法中,对该 Mock 对象设置一个返回值调用并断言from mock import patch
    from mock_.product_impl import Product
    
    @patch('mock_.product_impl.Product.get_product_status_by_id')
    def test_succuse(mock_get_product_status_by_id):
        # Mock方法,指定一个返回值
        mock_get_product_status_by_id.return_value = {"id": 1, "name": "苹果", "num": 23}
    
        product = Product()
    
        assert product.buy_product(1).get("status") == 0
    
    需要注意的是,Mock 此方法的时候,必须制定该方法的完整路径使用 @patch.object 同样能完成 Mock,不同的是,@patch.object 包含 2 个参数第一个参数为该方法所在的类;第二个参数为方法名from mock import patch
    
    from mock_.product_impl import Product
    
    # Mock一个方法
    # @patch.object:对象、方法名
    @patch.object(Product, 'get_product_status_by_id')
    def test_succuse(mock_get_product_status_by_id):
        # Mock方法,指定一个返回值
        mock_get_product_status_by_id.return_value = {"id": 1, "name": "苹果", "num": 23}
    
        product = Product()
    
        assert product.buy_product(1).get("status") == 0

    3.2 unittest.mock

    Python 3.3 之后,mock 作为标准库,已经内置到 unittest 中了

    还是以 3.1 的场景为例,使用 unittest 编写一个测试用例

    Mock 步骤如下:

  • 导入 unittest 框架中的 mock 文件
  • 实例化 Product 对象
  • mock.Mock(return_value=*) 方法对 get_product_status_by_id 方法进行 Mock
  • 调用并断言
  • import unittest
    from unittest import mock
    from unittest_mock.product_impl import Product
    class TestProduct(unittest.TestCase):
    def test_success(self):
    # 成功结果
    mock_success_value = {
    "id": 1, "name": "苹果", "num": 23}
    product = Product()
    product.get_product_status_by_id = mock.Mock(return_value=mock_success_value)
    # 调用实际函数
    assert product.buy_product(1).get("status") == 0
    if __name__ == "__main__":
    unittest.main()

    3.3 pytest.mock

    相比 unittest,pytest 由于强大的插件支持,用户群体可能更大!

    如果项目本身使用的框架是 pytest,则 Mock 更建议使用 pytest-mock 这个插件

    # pytest依赖
    pip3 install pytest

    Mock 步骤如下:

  • 使用 pytest 编写测试方法,参数为 mocker
  • 实例化 Product 对象
  • 使用 mocker.patch() 方法对 get_product_status_by_id 方法进行 Mock,并设置返回值
  • 调用并断言
  • import pytest
    from pytest_mock_.product_impl import Product
    def test_buy_product_success(mocker):
    """
    购买成功Mock
    :param mocker:
    :return:
    """

    # 实例化一个产品对象
    product = Product()
    # 对Product中的方法的返回值进行Mock
    mock_value = {
    "id": 1, "name": "苹果", "num": 23}
    # Mock方法
    # 注意:需要指定方法的完整路径
    # mocker.patch 的第一个参数必须是模拟对象的具体路径,第二个参数用来指定返回值
    product.get_product_status_by_id = mocker.patch(
    "product_impl.Product.get_product_status_by_id",
    return_value=mock_value)
    # 调用购买产品的方法
    result = product.buy_product(
    1)
    assert result.get("status") == 0

    需要注意的是,mocker.patch 方法第一个参数必须是 Mock 对象的完整路径

    4. 最后

    文中对 Python 中常见的 Mock 方案进行了讲解,实际应用中,建议根据项目实际情况进行选型。

    如果你觉得文章还不错,请大家 点赞、分享、留言 下,因为这将是我持续输出更多优质文章的最强动力!

    相关推荐

    全网第一个讲清楚CPK如何计算的Step by stepExcel和Python同时实现

    在网上搜索CPK的计算方法,几乎全是照搬教材的公式,在实际工作做作用不大,甚至误导人。比如这个又比如这个:CPK=min((X-LSL/3s),(USL-X/3s))还有这个,很规范的公式,也很清晰很...

    [R语言] R语言快速入门教程(r语言基础操作)

    本文主要是为了从零开始学习和理解R语言,简要介绍了该语言的最重要部分,以快速入门。主要参考文章:R-TutorialR语言程序的编写需要安装R或RStudio,通常是在RStudio中键入代码。但是R...

    Python第123题:计算直角三角形底边斜边【PythonTip题库300题】

    1、编程试题:编写一个程序,找出已知面积和高的直角三角形的另外两边(底边及斜边)。定义函数find_missing_sides(),有两个参数:area(面积)和height(高)。在函数内,计算另外...

    Tensor:Pytorch神经网络界的Numpy

    TensorTensor,它可以是0维、一维以及多维的数组,你可以将它看作为神经网络界的Numpy,它与Numpy相似,二者可以共享内存,且之间的转换非常方便。但它们也不相同,最大的区别就是Numpy...

    python多进程编程(python多进程进程池)

    forkwindows中是没有fork函数的,一开始直接在Windows中测试,直接报错importosimporttimeret=os.fork()ifret==0:...

    原来Python的协程有2种实现方式(python协程模型)

    什么是协程在Python中,协程(Coroutine)是一种轻量级的并发编程方式,可以通过协作式多任务来实现高效的并发执行。协程是一种特殊的生成器函数,通过使用yield关键字来挂起函数的执行...

    ob混淆加密解密,新版大众点评加密解密

    1目标:新版大众点评接口参数_token加密解密数据获取:所有教育培训机构联系方式获取难点:objs混淆2打开大众点评网站,点击教育全部,打开页面,切换到mobile模式,才能找到接口。打开开发者工具...

    python并发编程-同步锁(python并发和并行)

    需要注意的点:1.线程抢的是GIL锁,GIL锁相当于执行权限,拿到执行权限后才能拿到互斥锁Lock,其他线程也可以抢到GIL,但如果发现Lock仍然没有被释放则阻塞,即便是拿到执行权限GIL也要立刻...

    10分钟学会Python基础知识(python基础讲解)

    看完本文大概需要8分钟,看完后,仔细看下代码,认真回一下,函数基本知识就OK了。最好还是把代码敲一下。一、函数基础简单地说,一个函数就是一组Python语句的组合,它们可以在程序中运行一次或多次运行。...

    Python最常见的170道面试题全解析答案(二)

    60.请写一个Python逻辑,计算一个文件中的大写字母数量答:withopen(‘A.txt’)asfs:count=0foriinfs.read():ifi.isupper...

    Python 如何通过 threading 模块实现多线程。

    先熟悉下相关概念多线程是并发编程的一种方式,多线程在CPU密集型任务中无法充分利用多核性能,但在I/O操作(如文件读写、网络请求)等待期间,线程会释放GIL,此时其他线程可以运行。GIL是P...

    Python的设计模式单例模式(python 单例)

    单例模式,简单的说就是确保只有一个实例,我们知道,通常情况下类其实可以有很多实例,我们这么来保证唯一呢,全局访问。如配置管理、数据库连接池、日志处理器等。classSingleton: ...

    更安全的加密工具:bcrypt(bcrypt加密在线)

    作为程序员在开发工作中经常会使用加密算法,比如,密码、敏感数据等。初学者经常使用md5等方式对数据进行加密,但是作为严谨开发的程序员,需要掌握一些相对安全的加密方式,今天给大家介绍下我我在工作中使用到...

    一篇文章搞懂Python协程(python协程用法)

    前引之前我们学习了线程、进程的概念,了解了在操作系统中进程是资源分配的最小单位,线程是CPU调度的最小单位。按道理来说我们已经算是把cpu的利用率提高很多了。但是我们知道无论是创建多进程还是创建多线...

    Python开发必会的5个线程安全技巧

    点赞、收藏、加关注,下次找我不迷路一、啥是线程安全?假设你开了一家包子铺,店里有个公共的蒸笼,里面放着刚蒸好的包子。现在有三个顾客同时来拿包子,要是每个人都随便伸手去拿,会不会出现混乱?比如第一个顾...

    取消回复欢迎 发表评论: