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

PyTest中如何patch模块变量?loaded_data patch失败求助

问题解决方案

核心问题分析

你遇到的属性错误,本质是patch路径与函数内部变量引用的绑定关系不匹配:如果测试文件中直接导入update_data函数,函数会提前绑定原模块的loaded_data变量,此时单纯patch模块级的loaded_data不会生效;或者patch的目标路径写法有误。

具体解决方案

方案1:修正Patch路径与调用方式

如果不想修改原代码,确保测试时调用模块内的函数,同时patch模块级变量:

# 测试文件中导入整个datamanager模块
import datamanager
from unittest.mock import patch

def test_update_models():
    mock_loaded_data = {'some_data': 'data_file'}
    # patch模块级的loaded_data
    with patch('datamanager.loaded_data', new=mock_loaded_data):
        # 调用模块内的update_data函数,而非直接导入的函数
        datamanager.update_data()

或者如果必须直接导入函数,可patch函数__globals__中的变量:

from datamanager import update_data
from unittest.mock import patch

def test_update_models():
    mock_loaded_data = {'some_data': 'data_file'}
    with patch('datamanager.update_data.__globals__["loaded_data"]', new=mock_loaded_data):
        update_data()

方案2:重构代码,让函数更易测试

这是更推荐的做法——摆脱对模块级变量的硬依赖,将loaded_data作为可选参数传入函数:

修改datamanager.py中的update_data函数:

def update_data(loaded_data=None):
    # 如果未传参,使用模块级变量作为默认值
    if loaded_data is None:
        loaded_data = globals()['loaded_data']
    for key, current_model in loaded_data.items():
        mod_dir = os.path.join(BASE_DIR, key)
        if not os.path.exists(mod_dir):
            print("Model dir not present")
            continue
        model_files = os.listdir(mod_dir)
        if not model_files:
            print("Model dir is empty")
            continue

测试时直接传入mock数据,无需patch:

from datamanager import update_data

def test_update_models():
    mock_loaded_data = {'some_data': 'data_file'}
    update_data(loaded_data=mock_loaded_data)

方案3:结合Patch验证路径检查逻辑

你的核心需求是验证mod_dir不存在时的逻辑,所以需要同时mockos.path.exists返回False,并验证打印行为:

import datamanager
from unittest.mock import patch

def test_update_models():
    mock_loaded_data = {'some_data': 'data_file'}
    with patch('datamanager.loaded_data', new=mock_loaded_data), \
         patch('datamanager.os.path.exists', return_value=False), \
         patch('builtins.print') as mock_print:
        datamanager.update_data()
        # 验证是否触发了预期的打印
        mock_print.assert_called_with("Model dir not present")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 16:52:30