Karthikeyan Singaravelan <tir.kar...@gmail.com> added the comment:
I think the original issue with patch.object reported by Carl is different from the one reported by David for autospec. Analyzed the report by David and When we call autospec on a class with instance=True then the spec is modeled on the signature of __call__ instead of __init__ where __call__ has the signature of (self, x) and self is discarded with _eat_self passed as True. But mock also stores _spec_signature that is not aware of skipping self and has the signature as (self, x) and is used for checking signature in mock.assert_called_with. When instance=True then kwargs['_spec_as_instance']=True so does it makes sense to set kwargs['_eat_self'] = True at [0] ? I applied the change and there are no test failures so this deserves a test. This makes __call__ to have a different signature when it's called from mock and when the call is checked with assert_called_with_once. But it's not the case for methods of the class where self is skipped both for mock and _spec_signature. Since __signature__ is set for mock with my PR this makes it little easy to debug. Can this be dealt as a separate issue? I would also love to see if the assertion message can be improved since expected_call and actual_call are printed with repr version of the call object in spite of the signature failure. This has caused confusion here and in other places like issue26752 and issue25312. Sample program to demonstrate difference in signatures : import inspect from unittest import mock class Foo: def __call__(self, x): return x def bar(self, x): pass m = mock.create_autospec(Foo, instance=True) m(7) m.bar(7) print(inspect.signature(m)) print(m._spec_signature) print(inspect.signature(m.bar)) print(m.bar._spec_signature) m.bar.assert_called_once_with(7) # 7 passed as self with no value for x m.assert_called_once_with(7) # Fails due to self (x) (self, x) # self is not skipped in _spec_signature (x) (x) TypeError: missing a required argument: 'x' The above exception was the direct cause of the following exception: Traceback (most recent call last): File "../backups/bpo27715_1.py", line 20, in <module> m.assert_called_once_with(7) File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/unittest/mock.py", line 840, in assert_called_once_with return self.assert_called_with(*args, **kwargs) File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/unittest/mock.py", line 827, in assert_called_with raise AssertionError(_error_message()) from cause AssertionError: Expected call: mock(7) Actual call: mock(7) [0] https://github.com/python/cpython/blob/f8e9bd568adf85c1e4aea1dda542a96b027797e2/Lib/unittest/mock.py#L2199 ---------- nosy: +cjw296, mariocj89 versions: -Python 3.6 _______________________________________ Python tracker <rep...@bugs.python.org> <https://bugs.python.org/issue27715> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com