包装它时的python模拟属性 setter

标签 python properties mocking unit-testing

如何在包装 python 属性 setter 时模拟它(即调用原始 setter )?最直接的方法是访问 __set__,但它对属性是只读的,因此不起作用。

from unittest import TestCase
from unittest.mock import patch, PropertyMock


class SomeClass:
    def __init__(self, value):
        self._value = value

    @property
    def value(self):
        return self._value + 1

    @value.setter
    def value(self, value):
        self._value = value + 1


class TestSomeClass(TestCase):
    def test_value_setter(self):
        instance = SomeClass(0)
        with patch.object(SomeClass.value, '__set__', wraps=SomeClass.value.__set__) as value_setter:
            instance.value = 1
            value_setter.assert_called_with(instance, 1)
        self.assertEquals(instance.value, 3)

文档中还有 new_callable=PropertyMock,我尝试将它与 wrap 结合使用,但还没有成功。

最佳答案

您需要替换整个property 对象;您不能简单地更换二传手。这意味着您需要提供一个新的 property 对象,其中 setter 是原始 setter 的模拟包装器(通过 property.fset 属性访问):

setter_mock = Mock(wraps=SomeClass.value.fset)
mock_property = SomeClass.value.setter(setter_mock)
with patch.object(SomeClass, 'value', mock_property):
    instance.value = 1
    setter_mock.assert_called_with(instance, 1)

我在这里重用了@property.setter装饰器;它返回一个新的 property 对象,其中包含原始 property 的所有属性,除了 setter 被传入的任何内容替换;见How does the @property decorator work?

关于包装它时的python模拟属性 setter ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27864265/

相关文章:

java - 如何模拟更改实例属性状态的 void 方法

python - 在 python-textual 中动态确定小部件的高度

java - 任何以注释方式在没有Spring的情况下读取属性文件的API

python - 碰撞检测程序在 Turtle 中不起作用

python 基维 : animation won't run when called from clock event

c# - 如何在 Visual Studio C# 中正确公开 List<object> 属性?

grails - 从grails 2.3.4迁移到3.3.8时无法模拟域

unit-testing - mock 还是不 mock ?

python - 如何在 Pycharm 中运行代码

python - 类型错误:列表索引必须是整数,而不是 unicode(Telepot 检索名称)