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

如何向PropertyMock传递self参数?Mock属性遇参数缺失报错

问题描述

Mock普通类方法时,设置autospec=True可以自动传递self参数:

def do_thing_side_effect(self):
    pass

mocker.patch('module.class.do_thing', side_effect=do_thing_side_effect, autospec=True)

但Mock类属性的getter方法时,无论设置autospec=True还是spec=True,self参数都无法被传递,触发TypeError:

def thing_side_effect(self):
    pass

mocker.patch('module.class.thing', new=mocker.PropertyMock(side_effect=thing_side_effect, autospec=True))

报错信息:

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/unittest/mock.py", line 2848, in __get__
    return self()
  File "/usr/local/lib/python3.9/unittest/mock.py", line 1092, in __call__
    return self._mock_call(*args, **kwargs)
  File "/usr/local/lib/python3.9/unittest/mock.py", line 1096, in _mock_call
    return self._execute_mock_call(*args, **kwargs)
  File "/usr/local/lib/python3.9/unittest/mock.py", line 1157, in _execute_mock_call
    result = effect(*args, **kwargs)
TypeError: thing_side_effect() missing 1 required positional argument: 'self'

尝试替换为spec参数、使用new_callable搭配spec,都会触发相同错误。

解决方案

方法1:用Lambda包装副作用函数

通过lambda捕获属性访问时的实例参数,再手动传递给你的副作用函数:

def thing_side_effect(self):
    return f"mocked value for {self}"

mocker.patch(
    'module.class.thing',
    new=mocker.PropertyMock(side_effect=lambda self: thing_side_effect(self))
)

方法2:让副作用函数兼容无参调用

直接修改副作用函数,使其接受任意参数并提取实例:

def thing_side_effect(*args):
    self = args[0] if args else None
    # 这里编写依赖self的逻辑,比如访问self的其他属性
    return "mocked property value"

mocker.patch('module.class.thing', new=mocker.PropertyMock(side_effect=thing_side_effect))

方法3:自定义PropertyMock子类

重写PropertyMock的__get__方法,强制将实例传递给副作用函数:

from unittest.mock import PropertyMock

class SelfAwarePropertyMock(PropertyMock):
    def __get__(self, instance, owner):
        if self.side_effect:
            return self.side_effect(instance)
        return super().__get__(instance, owner)

def thing_side_effect(self):
    return self.some_other_attribute

mocker.patch('module.class.thing', new=SelfAwarePropertyMock(side_effect=thing_side_effect))

关键原因

普通方法Mock时,autospec=True会模拟方法的绑定行为,自动把实例作为第一个参数传给副作用函数。但PropertyMock本质是模拟描述符,它的默认__get__方法调用副作用函数时不会自动传递实例参数,因此需要手动处理实例的传递逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 16:25:35