This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author xtreak
Recipients cjw296, mariocj89, michael.foord, uranusjr, xtreak
Date 2019-08-01.05:43:20
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1564638200.74.0.654095514122.issue25312@roundup.psfhosted.org>
In-reply-to
Content
Using spec only checks for the attribute to be present and not the signature of the actual attribute being called. You might need autospec for this behavior. The below example to use create_autospec does the correct validation for mock_foo.func. There is an open issue to make spec also do signature validation but it could go into 3.9 only if accepted since it changes semantics : issue30587. Regarding the error message being cryptic there are other issues open on assertion error being displayed with actual and expected call list being same. I would propose closing this issue. Maybe the docs could be updated about this behavior to make sure using spec is more clear on the expected behavior.

https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock

spec: This can be either a list of strings or an existing object (a class or instance) that acts as the specification for the mock object. If you pass in an object then a list of strings is formed by calling dir on the object (excluding unsupported magic attributes and methods). Accessing any attribute not in this list will raise an AttributeError.

# bpo25312.py

from unittest.mock import call, create_autospec, Mock
import inspect

class Foo:

    def __init__(self, val):
        pass

    def func(self):
        pass

class FooMock(Mock):

    def _get_child_mock(self, **kwargs):
        return create_autospec(Foo)

mock_foo = FooMock()
print(inspect.signature(mock_foo.func)) # Signature is correct with create_autospec whereas with Mock(spec=Foo) it is (*args, **kwargs)
mock_foo.func() # Raises TypeError with (val) being signature.
mock_foo.func.assert_has_calls([call()])


➜  cpython git:(master) ✗ ./python.exe bpo25312.py
(val)
Traceback (most recent call last):
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/bpo25312.py", line 19, in <module>
    mock_foo.func()
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/unittest/mock.py", line 1027, in __call__
    self._mock_check_sig(*args, **kwargs)
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/unittest/mock.py", line 119, in checksig
    sig.bind(*args, **kwargs)
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/inspect.py", line 3025, in bind
    return self._bind(args, kwargs)
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/inspect.py", line 2940, in _bind
    raise TypeError(msg) from None
TypeError: missing a required argument: 'val'
History
Date User Action Args
2019-08-01 05:43:20xtreaksetrecipients: + xtreak, cjw296, michael.foord, uranusjr, mariocj89
2019-08-01 05:43:20xtreaksetmessageid: <1564638200.74.0.654095514122.issue25312@roundup.psfhosted.org>
2019-08-01 05:43:20xtreaklinkissue25312 messages
2019-08-01 05:43:20xtreakcreate