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

使用pytest无法Mock Python类私有实例变量__return_data的问题

解决pytest中Mock类私有实例变量失败的问题

问题根源

你用mocker.patch("temp.A._A__return_data")修改的是类的属性,但self.__return_data是实例变量,在类的__init__方法里会被重新赋值为dict(),所以你对类属性的patch完全不会作用到实例创建后的私有变量,导致实例的_A__return_data还是空字典,触发AttributeError。

可行解决方案

方案一:直接修改实例的私有变量(最简单直接)

创建实例后,直接给实例的改写后变量赋值(Python私有变量会被自动改写为_类名__变量名):

@pytest.fixture
def fixture_return_value():
    p = A()
    # 直接设置实例的私有变量(注意名称改写后的格式)
    p._A__return_data = {'key1': {'key2': ""}}
    return p

测试函数调整为使用fixture中已配置好的实例:

def test_func1(fixture_return_value):
    response = fixture_return_value.func1()
    print("response ", response)
    assert response == {'msg': 'Failed, Missing key 1', 'response': False, 'data': {}}

方案二:Mock类的__init__方法

替换原有的__init__方法,让它初始化时设置我们需要的私有变量:

@pytest.fixture
def fixture_return_value(mocker):
    # 自定义mock的__init__方法
    def mock_init(self):
        self.__return_data = {'key1': {'key2': ""}}
    
    # 替换A类的__init__方法
    mocker.patch.object(A, '__init__', side_effect=mock_init)
    return A()

方案三:重构代码(最佳实践)

直接mock私有变量属于测试内部实现细节,不是推荐的做法。如果__return_data是从外部获取的(比如接口、文件、其他方法),建议把数据获取逻辑抽成单独的方法,再mock这个方法:

修改待测试类:

class A():
    def __init__(self):
        # 把数据获取逻辑抽成独立方法
        self.__return_data = self._fetch_return_data()

    def _fetch_return_data(self):
        # 原来获取数据的逻辑(比如调用外部接口、读取配置等)
        return dict()

    def func1(self):
        try:
            if not self.__return_data['key1']['key2']:
                return generate_error('Failed, Missing key1')
            # ... 其他业务逻辑
        except Exception as e:
            # ... 异常处理

测试代码:

@pytest.fixture
def fixture_return_value(mocker):
    # mock抽取后的方法,返回我们需要的测试数据
    mocker.patch.object(A, '_fetch_return_data', return_value={'key1': {'key2': ""}})
    return A()

这种方式测试的是类的行为而非内部实现细节,测试更稳定,后续代码重构也不容易破坏测试。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 10:15:36