I am trying to mock a property of a class (@property decorator) and have bumped into this incorrect behaviour:
>>> from mock import MagicMock, PropertyMock
>>> m = MagicMock()
>>> type(m).p = PropertyMock(side_effect=AttributeError)
>>> m.p
<MagicMock name='mock.p' id='63150736'>
The correct behaviour is this:
>>> from mock import MagicMock, PropertyMock
>>> m = MagicMock()
>>> type(m).p = PropertyMock(side_effect=ValueError)
>>> m.p
Traceback (most recent call last)
[...]
ValueError
I cannot fathom why setting a different exception is giving me different results. The expected result in both cases is that the exception should be raised! So, the In[4] line should raise an AttributeError
. It does not.
Anyone care to enlighten me?
Addendum: The property I am trying to check does some clever checking to see if the value passed is sane. If said value is not sane, it returns AttributeError as I understand that this is the correct exception in Python. So, I need to check the code that uses the property for failure as well as success. Thus, using a MagicMock to mock the property and raise said exception. A trivial example would be:
@x.setter
def x(self, value):
if value < 0:
raise AttributeError("Value cannot be negative!")
self._x = value
I know this question is old, but I've just had the same problem and found this question. Also the bug report submitted almost two years ago didn't seem to get any attention, so I thought I'll share the solution I found just in case anybody else will have this problem.
So, as stated PropertyMock
doesn't work with AttributeError
set as a side_effect
. The workaround is to create a simple Mock
with a spec
attribute set to an empty list
like this:
>>> from mock import Mock
>>> m = Mock(spec=[])
>>> m.p
Traceback (most recent call last)
[...]
AttributeError
As stated in the docs:
spec: This can be either a list of strings or an existing object (a class or instance) that acts as the specification for the mock object. If you pass in an object then a list of strings is formed by calling dir on the object (excluding unsupported magic attributes and methods). Accessing any attribute not in this list will raise an AttributeError.
Er, hold the phone. Does this cover your use case?
>>> 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
I stumbled across that in the docs while looking for something entirely different.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With