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

如何在pytest中全局mock函数write_sql的所有实例?

全局Mock write_sql 所有实例的优化方案

问题背景

你当前通过为每个使用write_sql的模块单独编写fixture实现Mock,但存在重复代码问题。直接Mockwrite_sql所属的原模块sql_services无效,原因是业务模块采用from sql_services import write_sql的导入方式——这会在模块本地命名空间创建一个指向原函数的独立引用,后续调用的是该本地引用,而非原模块的函数。

解决方案

方案1:统一导入方式(推荐,若允许修改业务代码)

将所有业务模块的导入方式改为引用原模块的形式,而非直接导入函数:

修改sandbox.py(及其他类似模块):

import sql_services

def do_a_write():
   df = # logic to populate a dataframe
   sql_services.write_sql(df, "schema.table")

此时只需保留一个全局fixture即可Mock所有调用:

# conftest.py
import pytest
from unittest.mock import MagicMock
from ds_services import sql_services

@pytest.fixture(autouse=True)
def mock_write_sql(monkeypatch):
    mock = MagicMock()
    monkeypatch.set_attr(sql_services, "write_sql", mock)
    return mock

方案2:批量Mock所有目标模块(无需修改业务代码)

如果无法调整业务代码的导入方式,可以在单个fixture中批量处理所有需要Mock的模块,避免重复编写fixture:

基于monkeypatch实现

# conftest.py
import pytest
from unittest.mock import MagicMock

@pytest.fixture(autouse=True)
def mock_all_write_sql(monkeypatch):
    mock_write = MagicMock()
    # 列出所有导入了write_sql的模块路径
    target_modules = [
        "sandbox.write_sql",
        "sandbox2.write_sql",
        # 添加其他需要Mock的模块路径
    ]
    for target in target_modules:
        monkeypatch.set_attr(target, mock_write)
    return mock_write

基于pytest-mock插件实现(更简洁)

先安装插件:pip install pytest-mock,然后编写fixture:

# conftest.py
import pytest
from unittest.mock import MagicMock

@pytest.fixture(autouse=True)
def mock_all_write_sql(mocker):
    mock_write = MagicMock()
    # 批量指定需要Mock的目标
    targets = {
        "sandbox.write_sql": mock_write,
        "sandbox2.write_sql": mock_write,
        # 添加其他目标
    }
    mocker.patch.multiple(**targets)
    return mock_write

说明

方案1从根源上避免了多模块Mock的重复工作,是更优的长期解决方案;方案2适用于无法修改业务代码的场景,通过批量处理减少重复代码。

内容的提问来源于stack exchange,提问作者Jacob Gladman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 06:00:06