Use create_autospec
:
from unittest import mock
class A:
def f(self): pass
m = mock.create_autospec(A)
m.f()
m.f.assert_called_once() # works OK
m.f.misstyped_called_once() # raises
Traceback (most recent call last):
File "/Users/ant/opt/miniconda3/envs/deeplearning/lib/python3.8/site-packages/IPython/core/interactiveshell.py", line 3437, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-85-8fe8ab09b722>", line 7, in <module>
m.f.misstyped_called_once() # raises
File "/Users/ant/opt/miniconda3/envs/deeplearning/lib/python3.8/unittest/mock.py", line 637, in __getattr__
raise AttributeError("Mock object has no attribute %r" % name)
AttributeError: Mock object has no attribute 'misstyped_called_once'
It turns out there's a whole section devoted to this topic in the docs: https://docs.python.org/3/library/unittest.mock.html#autospeccing
Autospeccing is based on the existing spec feature of mock. It limits the api of mocks to the api of an original object (the spec), but it is recursive (implemented lazily) so that attributes of mocks only have the same api as the attributes of the spec.
EDIT
Looks there's a school of thought that avoids using the assert_called_xxx
in favour of explicit
assert mock_restart.call_count == 1
assert mock_restart.call_args == mock.call(“some argument”)
and another school that proposes a methodological solution -- if you do TDD, then your test must fail before you put in any implementation and this guards against the false positives.