This is a toy version of a setup I have:
import mock
import functools
def quux(f):
@functools.wraps(f)
def wrapper(self, *args, **kwargs):
return f(self, 'spam', *args, **kwargs)
return wrapper
class Foo:
@quux
def bar(self, baz):
pass
mock_foo = mock.create_autospec(Foo())
mock_foo.bar()
This works in python 2, but fails in python 3 with:
Traceback (most recent call last):
File "thing.py", line 17, in <module>
mock_foo.bar()
File "./venv/lib/python3.6/site-packages/mock/mock.py", line 1061, in __call__
_mock_self._mock_check_sig(*args, **kwargs)
File "./venv/lib/python3.6/site-packages/mock/mock.py", line 209, in checksig
sig.bind(*args, **kwargs)
File "/usr/lib/python3.6/inspect.py", line 2934, in bind
return args[0]._bind(args[1:], kwargs)
File "/usr/lib/python3.6/inspect.py", line 2849, in _bind
raise TypeError(msg) from None
TypeError: missing a required argument: 'baz'
Originally I tried using makefun and edit the signature to remove the baz parameter, since in my real setup, the value is always injected as the first parameter before the method.
I would like to be able to keep autospeccing my mocks to make sure that functions are called properly during tests. However, since I would like to run on python 3 at some point, this setup is untenable.
Side note: one of the roadblocks I ran into was I sometimes needed to wrap callable objects instead of functions, so my ideal solution works for those as well.