Побочный эффект 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
Я наткнулся на это в в документах, ища что-то совершенно другое.