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

使用unittest和mock测试全局变量列表更新时断言失败问题

问题分析与修复方案

先贴出你提供的代码:

file.py

GLOB_VAR = []

def my_func(x, msg):
    if x:
        logging.warning(msg)
    GLOB_VAR.append(x)

test.py(原代码)

@patch('file.GLOB_VAR', [])
@patch('logging.Logger.warning')
def test_file_with_msg(self, logging):
    x = 'test_x'
    msg = 'test_msg'

    my_func(x=x, msg=msg)
    logging.assert_called_with(message)
    assert x in GLOB_VAR

问题根源

  1. 笔误导致的前置错误:logging.assert_called_with(message)里的message未定义,实际应该用你定义的msg,这行代码会先抛出NameError,根本走不到断言步骤。
  2. 全局变量引用不匹配:@patch('file.GLOB_VAR', [])是把file模块中的GLOB_VAR替换成了一个全新的空列表,但如果你的测试代码是通过from file import GLOB_VAR导入的变量,这个导入的GLOB_VAR指向的是原全局列表,而my_func操作的是被patch后的新列表,所以断言x in GLOB_VAR必然失败。

修复方案

根据你“需要保留全局变量”的需求,分两种场景处理:

场景1:测试时临时替换全局变量,不影响原变量状态

用patch的new_callable参数创建临时列表,同时在测试中通过模块引用被patch后的变量:

from unittest.mock import patch
import file
from file import my_func
import logging

class TestMyFunc:
    # 用new_callable创建新的空列表,不会修改原全局变量
    @patch('file.GLOB_VAR', new_callable=list)
    @patch('logging.Logger.warning')
    def test_file_with_msg(self, mock_warning, mock_glob_var):
        x = 'test_x'
        msg = 'test_msg'

        my_func(x=x, msg=msg)
        # 修正笔误,用正确的变量名msg
        mock_warning.assert_called_with(msg)
        # 通过file模块访问被patch后的全局变量
        assert x in file.GLOB_VAR
        # 或者直接用mock_glob_var参数访问
        assert x in mock_glob_var

场景2:测试后保留原全局变量的修改(即测试后GLOB_VAR确实包含x)

直接去掉@patch('file.GLOB_VAR', []),手动控制全局变量的状态:

from unittest.mock import patch
import file
from file import my_func
import logging

class TestMyFunc:
    @patch('logging.Logger.warning')
    def test_file_with_msg(self, mock_warning):
        x = 'test_x'
        msg = 'test_msg'
        # 测试前备份原状态(可选,根据是否需要恢复)
        original_data = file.GLOB_VAR.copy()
        file.GLOB_VAR.clear()

        my_func(x=x, msg=msg)
        mock_warning.assert_called_with(msg)
        # 直接断言模块中的全局变量
        assert x in file.GLOB_VAR

        # 测试后恢复原状态(如果不需要保留测试数据,就加上这段)
        file.GLOB_VAR.clear()
        file.GLOB_VAR.extend(original_data)

关键说明

  • 永远通过模块(比如file.GLOB_VAR)访问全局变量,而不是直接导入后使用,避免引用不匹配的问题。
  • 如果只是测试逻辑不需要保留原全局变量,用new_callable的方式更安全,不会污染原变量状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 17:15:37