You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将多段mock.patch的with语句封装为可复用函数?

问题描述

编写单元测试时需要重复Mock大量对象,当前使用mock.patch的代码如下:

with mock.patch("project.folder.file.SomeClass.method") as mock_this,
     mock.patch("otherproj.directory.file.AnotherClass.some_method") as mock_that,
     ... 还有另外4个类似Mock ...                           :

    mock_this.return_value = True
    mock_that.side_effect = some_side_effect
    ... 更多配置 ...

希望封装成名为server_mock_boilerplate的函数,实现如下使用方式:

# 可能需要传入对象以处理全局变量Mock的情况
# 我可能只需要获取部分Mock对象
with server_mock_boilerplate(obj1, obj2) as (mock1, mock2, mock4):
    # 执行测试
       ...
    # 测试中可能修改side_effect
    mock1.side_effect = something_else

困惑点:直接从with返回会关闭资源,不通过with激活的话mock.patch返回的不是MagicMock类型,不知道如何封装重复的with条目并获取指定Mock元组。

解决方案

用contextlib.contextmanager装饰器创建自定义上下文管理器,整合所有mock.patch操作,激活后配置默认Mock行为,最后yield出需要的Mock对象元组,退出时自动清理所有Patch。

实现代码

from contextlib import contextmanager
import mock

@contextmanager
def server_mock_boilerplate(obj1=None, obj2=None):
    # 定义所有需要Patch的目标路径
    patch_targets = [
        "project.folder.file.SomeClass.method",
        "otherproj.directory.file.AnotherClass.some_method",
        # 补充另外4个需要Patch的路径
        "third.target.module.Class.method",
        "fourth.target.module.function",
        "fifth.target.Class.attribute",
        "sixth.target.util.func"
    ]
    
    # 创建所有Patch对象
    patches = [mock.patch(target) for target in patch_targets]
    
    # 激活所有Patch,获取对应的Mock实例
    mocks = []
    for patch in patches:
        mock_instance = patch.start()
        mocks.append(mock_instance)
    
    try:
        # 配置默认的Mock行为
        mocks[0].return_value = True  # 对应原代码中的mock_this
        mocks[1].side_effect = some_side_effect  # 对应原代码中的mock_that
        # 补充其他Mock的默认配置
        
        # 处理传入的全局变量对象(如果有需求)
        if obj1:
            # 示例:对obj1的某个属性做额外Mock或调整
            # mock.patch.object(obj1, "attr", return_value="test").start()
            pass
        if obj2:
            pass
        
        # 返回需要的Mock元组,按需选择对应位置的Mock
        yield (mocks[0], mocks[1], mocks[3])
    finally:
        # 确保所有Patch都停止,清理资源
        for patch in patches:
            patch.stop()

使用说明

  • 在with语句中可直接拿到指定的Mock对象,测试过程中能随时修改side_effect、return_value等属性
  • 若要调整返回的Mock集合,只需修改yield语句中的元组内容即可
  • 传入的obj1、obj2可用于处理全局变量的特殊Mock场景,在try代码块中添加对应逻辑即可

内容的提问来源于stack exchange,提问作者Tomáš Zato

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 06:47:36