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

如何用Pytest Patch Mock全局变量并避免调用外部服务器函数

解决Pytest中全局变量依赖外部函数的测试问题

问题核心

你的测试代码之所以失败,是因为模块导入阶段就自动执行了server_function_1()。当你在测试文件里写import my_module时,global_result_of_server_func已经被真实函数赋值(甚至直接报错),后续的patch操作根本无法回溯修改这个已经初始化完成的全局变量。


可行解决方案

方案一:在模块导入前完成函数Patch

修改测试逻辑,先mock目标函数,再导入模块,让模块初始化时调用的是mock后的函数。

修改后的test_my_module.py代码:

import pytest
from unittest import mock
import datetime
import logging
import sys

logger = logging.getLogger(__name__)
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)

frozen_time = datetime.datetime(year=2022, month=6, day=1, hour=1, minute=0, second=0, microsecond=0)
mock_server_str = "Mock Server String"

class TestMyModule():
    def test_handler(self):
        # 先patch目标函数,再导入模块
        with mock.patch("my_module.server_function_1", return_value=mock_server_str):
            import my_module
            # 再patch时间函数
            with mock.patch("my_module.get_current_datetime_str", return_value=frozen_time.strftime('%Y%m%d.%H%M%S.%f')):
                test_server_val, test_frozen_time = my_module.some_function()
                assert test_frozen_time == frozen_time.strftime('%Y%m%d.%H%M%S.%f')
                assert test_server_val == mock_server_str

方案二:重构原模块,延迟全局变量初始化

如果允许修改原模块,将全局变量的初始化逻辑封装到函数中,避免模块导入时自动执行。

修改后的my_module.py:

import datetime

def server_function_1():
    try:
        return_val = "Assume the external server function returns a string"
    except Exception as e:
        print("Failed")
        print(e)
        raise e
    else:
        return return_val
    finally:
        raise Exception("Cannot connect to server")

# 封装全局变量初始化逻辑
def init_global():
    global global_result_of_server_func
    global_result_of_server_func = server_function_1()

# 保留正常使用时的自动初始化行为
init_global()

def get_current_datetime_str():
    return datetime.datetime.now().strftime('%Y%m%d.%H%M%S.%f')

def some_function():
    return global_result_of_server_func, get_current_datetime_str()

对应的测试文件写法:

import pytest
from unittest import mock
import datetime
import logging
import sys

logger = logging.getLogger(__name__)
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)

frozen_time = datetime.datetime(year=2022, month=6, day=1, hour=1, minute=0, second=0, microsecond=0)
mock_server_str = "Mock Server String"

# 导入前patch,避免初始化时调用真实函数
with mock.patch("my_module.server_function_1", return_value=mock_server_str):
    import my_module

class TestMyModule():
    def test_handler(self):
        with mock.patch("my_module.get_current_datetime_str", return_value=frozen_time.strftime('%Y%m%d.%H%M%S.%f')):
            test_server_val, test_frozen_time = my_module.some_function()
            assert test_frozen_time == frozen_time.strftime('%Y%m%d.%H%M%S.%f')
            assert test_server_val == mock_server_str

内容的提问来源于stack exchange,提问作者Kevin Tianyu Xu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 19:33:23