Mario Corchero <marioc...@gmail.com> added the comment:
Quite a tricky bug! Indeed @xtreak the `_call_matcher` is using the `__init__` signature. I think this is a bug introduced in https://bugs.python.org/issue17015. There is a mix of the fact that spec in Mock also can accept classes (not instances) whilst spec requires the user to say whether what you are passing is a class or an instance. This gets messed up when validating the calls as at validation time it tries to match the signature as done in issue17015 (something that is useful for other cases as outlined in the issue). You can see how this is clearly a bug with the following reproducer: ``` from unittest.mock import Mock, call class X(object): def __init__(self):pass def foo(self, a):pass x = Mock(spec=X) x.foo(20) x.assert_has_calls(x.mock_calls) ``` Using an instance (`X()`) of the class "hides" the issue, as the right signature is used for validation. I am not sure if there is any easy fix here :/, but it is broken that the validation happens in different ways when a class is used in the spec (when calling it vs when validating it). Things "work" as if you use a spec of a class and then construct it, that passes fine as it does not get validated as attribute lookup and then there is no further validation. Maybe something like this would work: ``` --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -384,8 +384,10 @@ class NonCallableMock(Base): def __init__( self, spec=None, wraps=None, name=None, spec_set=None, parent=None, _spec_state=None, _new_name='', _new_parent=None, - _spec_as_instance=False, _eat_self=None, unsafe=False, **kwargs + _spec_as_instance=None, _eat_self=None, unsafe=False, **kwargs ): + if _spec_as_instance is None: + _spec_as_instance = isinstance(spec, type) # We might need to play with eat_self as well here. if _new_parent is None: _new_parent = parent @@ -2205,8 +2207,8 @@ def create_autospec(spec, spec_set=False, instance=False, _parent=None, elif spec is None: # None we mock with a normal mock without a spec _kwargs = {} - if _kwargs and instance: - _kwargs['_spec_as_instance'] = True + if _kwargs: + _kwargs['_spec_as_instance'] = instance ``` Basically, being explicit on auto_spec and inferring it on the creation of Mocks, but that might break some people who (probably badly) rely on the signature of the class. This issue probably needs some further work. ---------- _______________________________________ Python tracker <rep...@bugs.python.org> <https://bugs.python.org/issue26752> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com