包装时python模拟属性设置器

sim*_*ack 7 python unit-testing properties mocking

你如何在包装 python 属性设置器时模拟它(即调用原始设置器)?最直接的方法是访问__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)
Run Code Online (Sandbox Code Playgroud)

new_callable=PropertyMock文档中也有,我已经尝试将它与它结合,wrap但还没有让它工作。

Mar*_*ers 5

您需要替换整个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)
Run Code Online (Sandbox Code Playgroud)

我在@property.setter这里重用了装饰器;它返回一个property具有原始所有属性的新对象,property除了 setter 被传入的任何内容替换;请参阅@property 装饰器如何工作?