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

如何用pytest全局Fixture最小化代码量Mock函数?

全局Mock函数的最简实现方案

核心要点

Python里mock函数的关键是patch被调用模块里的目标函数引用——也就是work.get_id,而非原定义的utils.get_id。用pytest的全局自动生效fixture,能做到一次定义、所有测试复用,彻底减少样板代码。

具体步骤

1. 编写全局Fixture(conftest.py)

在项目根目录的conftest.py里定义这个fixture,设置autouse=True让所有测试自动生效:

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

@pytest.fixture(autouse=True)
def mock_get_id():
    # 重点:patch work模块里的get_id引用
    with patch('work.get_id') as mock:
        # 设置默认的mock返回值,按需修改
        mock.return_value = "mocked_id_123"
        yield mock

2. 测试用例(tests/test_work.py)

现在测试里完全不用写重复的patch代码,直接验证逻辑即可:

# tests/test_work.py
from work import do_work

def test_do_work():
    result = do_work()
    # 验证结果是否符合mock后的预期
    assert result == "processed: mocked_id_123"
    # 可选:检查get_id的调用参数和次数
    from work import get_id
    get_id.assert_called_once_with("default_param1", "default_param2")

3. 原模块参考代码

  • utils.py
# utils.py
def get_id(param1, param2):
    # 原业务逻辑,比如调用外部接口生成真实ID
    return f"real_id_{param1}_{param2}"
  • work.py
# work.py
from utils import get_id

def do_work():
    id = get_id("default_param1", "default_param2")
    return f"processed: {id}"

之前方案失效的原因

  • 方案2中直接patchutils.get_id没用:因为work.py已经把get_id的引用导入到自身模块里,patch原模块不会更新已导入的引用。
  • monkeypatch方案如果没找对目标(应该修改work.get_id而非utils.get_id),自然也无法生效。

扩展:个别测试自定义mock行为

要是某个测试需要不同的mock返回值,直接在测试里覆盖fixture的设置即可:

def test_do_work_custom_mock(mock_get_id):
    mock_get_id.return_value = "custom_mocked_id"
    result = do_work()
    assert result == "processed: custom_mocked_id"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 21:03:29