Побочный эффект Python PropertyMock с атрибутами AttributeError и ValueError

Я пытаюсь высмеять свойство класса (декоратор @property) и столкнулся с этим неправильным поведением:

 >>> from mock import MagicMock, PropertyMock
 >>> m = MagicMock()
 >>> type(m).p = PropertyMock(side_effect=AttributeError)
 >>> m.p
 <MagicMock name='mock.p' id='63150736'>

Правильное поведение таково:

 >>> from mock import MagicMock, PropertyMock
 >>> m = MagicMock()
 >>> type(m).p = PropertyMock(side_effect=ValueError)
 >>> m.p
Traceback (most recent call last)
[...]
ValueError

Я не могу понять, почему установка другого исключения дает мне разные результаты. Ожидаемый результат в обоих случаях заключается в том, что исключение должно быть поднято! Итак, строка In [4] должна поднять AttributeError. Это не так.

Кто-нибудь хочет просветить меня?

Добавление. Свойство, которое я пытаюсь проверить, делает некоторые умные проверки, чтобы проверить, является ли принятое значение нормальным. Если указанное значение не является нормальным, оно возвращает AttributeError, поскольку я понимаю, что это правильное исключение в Python. Итак, мне нужно проверить код, который использует свойство для сбоя, а также успех. Таким образом, используя MagicMock, чтобы издеваться над этим свойством и поднять указанное исключение. Тривиальный пример:

@x.setter
def x(self, value):
    if value < 0:
         raise AttributeError("Value cannot be negative!")
    self._x = value

Ответ 1

Я знаю, что этот вопрос старый, но у меня была такая же проблема и нашла этот вопрос. Также отчет об ошибках, представленный почти два года назад, похоже, не привлек к себе внимания, поэтому я решил поделиться решением, которое я нашел на всякий случай эта проблема.

Итак, как указано PropertyMock не работает с AttributeError, установленным как side_effect. Обходной путь состоит в том, чтобы создать простой Mock с атрибутом spec, установленным в пустой list следующим образом:

>>> from mock import Mock
>>> m = Mock(spec=[])
>>> m.p
Traceback (most recent call last)
[...]
AttributeError

Как указано в docs:

spec: Это может быть либо список строк, либо существующий объект (класс или экземпляр), который действует как спецификация для mock-объекта. Если вы передаете объект, тогда список строк формируется путем вызова dir объекта (исключая неподдерживаемые магические атрибуты и методы). Доступ к любому атрибуту, не указанному в этом списке, приведет к повышению атрибута AttributeError.

Ответ 2

Er, удерживайте телефон. Это покрывает ваш прецедент?

>>> import mock
>>> m = mock.MagicMock()
>>> m.p
<MagicMock name='mock.p' id='139756843423248'>
>>> del m.p #!
>>> m.p
Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
     File "/home/ahammel/bin/python/mock-1.0.1-py2.6.egg/mock.py", line 664, in __getattr__
         raise AttributeError(name)
     AttributeError: p

Я наткнулся на это в в документах, ища что-то совершенно другое.