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

Python pytest中Mock被函数赋值的全局变量以避免函数执行

解决pytest中mock全局变量赋值函数仍被执行的问题

问题原因

你当前的写法里,测试文件导入app.file2.VAR1时,Python会先执行file2.py的全部代码——也就是调用some_func()给VAR1赋值,这一步发生在@mock.patch生效之前。所以哪怕后面patch了VAR1,原函数some_func早已经被执行过了。

解决方案

核心思路是:在file2.py被导入执行前,先mock掉它依赖的some_func,这样VAR1赋值时调用的是mock后的函数,原函数根本不会被触发。

方法1:在测试函数内延迟导入file2

把from app.file2 import VAR1放到被patch装饰的测试函数内部,确保mock生效后再导入模块:

from unittest import mock
import pytest

@mock.patch('app.file2.some_func', return_value="mock的全局变量值")
def test_file_2_func(mock_some_func):
    # 此时mock已经生效,导入file2时会用mock后的函数赋值VAR1
    from app.file2 import VAR1
    print('made it to my test :)')
    print(VAR1)  # 输出"mock的全局变量值"
    # 还可以验证mock函数是否被调用
    assert mock_some_func.called

方法2:用fixture提前mock并控制导入时机

如果多个测试用例都需要这个mock,可以用pytest fixture来封装:

import pytest
from unittest import mock

@pytest.fixture
def mock_file2_some_func():
    # 进入fixture时patch,退出时自动还原
    with mock.patch('app.file2.some_func', return_value="mock值"):
        yield

def test_file_2(mock_file2_some_func):
    # 在fixture的mock生效后再导入
    from app.file2 import VAR1
    assert VAR1 == "mock值"

方法3:重新加载模块(适合已提前导入的场景)

如果测试文件已经提前导入了app.file2,可以先patch,再用importlib.reload重新加载模块,让模块重新执行赋值逻辑:

from unittest import mock
import pytest
import importlib
import app.file2  # 提前导入了模块

@mock.patch('app.file2.some_func', return_value="重新加载后的mock值")
def test_file_2_reload(mock_some_func):
    # 重新加载模块,此时会用mock后的函数赋值VAR1
    importlib.reload(app.file2)
    print(app.file2.VAR1)  # 输出"重新加载后的mock值"

关键注意点

  • mock的目标必须是**file2.py里引用的some_func**(即app.file2.some_func),而不是file1.py里的原函数,这是Python mock的"where it is used"原则。
  • 一定要确保mock在file2模块执行前生效,否则原函数必然会被调用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 06:30:47