Issue 45756: mock raises exception when using a spec with an attribute that raises exception on access (original) (raw)

In Python 3.8 and later creating a mock with a spec specifying an object containing a property that happens to raise an exception when accessed will fail, because _mock_add_spec calls getattr() on every attribute of the spec. This did not happen in Python 3.6/3.7.

This is likely a fairly unusual scenario (and in the particular case where I encountered this I could just use a class instead of an instance for the spec), but it was surprising.

For example:

cat test.py

from unittest import mock

class Foo: @property def bar(self) -> str: raise Exception('xxx')

m = mock.MagicMock(spec=Foo())

python3.11 test.py

Traceback (most recent call last): File "/root/test.py", line 8, in m = mock.MagicMock(spec=Foo()) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.11/unittest/mock.py", line 2069, in init _safe_super(MagicMixin, self).init(*args, **kw) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.11/unittest/mock.py", line 1087, in init _safe_super(CallableMixin, self).init( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.11/unittest/mock.py", line 442, in init self._mock_add_spec(spec, spec_set, _spec_as_instance, _eat_self) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.11/unittest/mock.py", line 497, in _mock_add_spec if iscoroutinefunction(getattr(spec, attr, None)): ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/root/test.py", line 6, in bar raise Exception('xxx') ^^^^^^^^^^^^^^^^^^^^^^ Exception: xxx