使用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
相关产品推荐
相关产品推荐

