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

pytest mocker测试间未重置Mock导致结果异常问题求助

pytest-mocker 上下文管理器patch后测试间数据污染问题解析

问题本质

你遇到的不是pytest-mocker或unittest.mock.patch的已知bug,也和导入无关,核心问题是两次测试复用了同一个被深拷贝后的对象实例。

上下文管理器确实会在单个测试结束后拆除补丁,但如果两次patch的return_value指向的是同一个对象,那么第一个测试中对该对象的修改会被第二个测试继承——因为列表、字典都是可变类型,深拷贝只做了一次,后续返回的都是这个已经被修改的实例。

错误示例(你可能的写法)

比如你的测试代码可能是这样的(全局复用了同一个mock数据实例):

import pytest
from unittest.mock import patch, deepcopy
from dummy_module import delete_d_key

# 全局定义深拷贝数据,两个测试都用它
original_data = [{'a':1, 'd':4}, {'b':2, 'd':5}]
mock_data = deepcopy(original_data)

def test_A():
    with patch('dummy_module.dummy_module_2.function_that_returns_list_of_dict', return_value=mock_data):
        delete_d_key()
        # 此时mock_data里的'd'键已经被删除

def test_B():
    with patch('dummy_module.dummy_module_2.function_that_returns_list_of_dict', return_value=mock_data):
        result = delete_d_key()
        # 这里读到的mock_data已经是test_A修改后的版本

修正方案

要确保每个测试拿到的都是全新的深拷贝实例,有两种常用方式:

  • 方式一:在每个测试内部生成深拷贝数据
import pytest
from unittest.mock import patch, deepcopy
from dummy_module import delete_d_key

original_data = [{'a':1, 'd':4}, {'b':2, 'd':5}]

def test_A():
    # 每个测试重新生成深拷贝实例
    mock_data = deepcopy(original_data)
    with patch('dummy_module.dummy_module_2.function_that_returns_list_of_dict', return_value=mock_data):
        delete_d_key()

def test_B():
    mock_data = deepcopy(original_data)
    with patch('dummy_module.dummy_module_2.function_that_returns_list_of_dict', return_value=mock_data):
        result = delete_d_key()
        # 此时拿到的是全新的未修改数据
  • 方式二:用side_effect返回新实例
    如果不想在每个测试里重复写深拷贝,可以用side_effect每次调用都返回新的深拷贝:
import pytest
from unittest.mock import patch, deepcopy
from dummy_module import delete_d_key

original_data = [{'a':1, 'd':4}, {'b':2, 'd':5}]

def test_A():
    def get_new_data():
        return deepcopy(original_data)
    with patch('dummy_module.dummy_module_2.function_that_returns_list_of_dict', side_effect=get_new_data):
        delete_d_key()

def test_B():
    def get_new_data():
        return deepcopy(original_data)
    with patch('dummy_module.dummy_module_2.function_that_returns_list_of_dict', side_effect=get_new_data):
        result = delete_d_key()

总结

  • 上下文管理器的patch拆除是正常工作的,问题出在可变对象实例的复用
  • 解决的核心是确保每个测试用例获取到的mock返回值都是独立的新实例
  • 这不属于框架bug,是可变类型在测试中常见的复用误区

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 04:40:08