Karthikeyan Singaravelan <tir.kar...@gmail.com> added the comment: mock.Mock doesn't do signature validation by default for constructor and methods. This is expected. create_autospec [0] should be used to make sure the signature is validated.'
import dataclasses import unittest.mock @dataclasses.dataclass class Foo: name: str baz: float bar: int = 12 FooMock = unittest.mock.create_autospec(Foo) fooMock = FooMock() # Will fail now since it's specced ➜ cpython git:(master) ./python.exe ../backups/bpo36580.py Traceback (most recent call last): File "../backups/bpo36580.py", line 11, in <module> fooMock = FooMock() # should fail: Foo.__init__ takes two arguments File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/unittest/mock.py", line 984, in __call__ _mock_self._mock_check_sig(*args, **kwargs) File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/unittest/mock.py", line 103, in checksig sig.bind(*args, **kwargs) File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/inspect.py", line 3021, in bind return args[0]._bind(args[1:], kwargs) File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/inspect.py", line 2936, in _bind raise TypeError(msg) from None TypeError: missing a required argument: 'name' On the other hand 'name' in dir(FooMock) doesn't have the attributes (name and baz) present I suppose they are constructed dynamically when an object is created from Foo since they are present in dir(Foo()) and mock is not able to detect them? mock.create_autospec does an initial pass of dir(Foo) to copy the attributes [1] and perhaps it's not able to copy name and bar while baz is copied. Below are for FooMock = create_autospec(Foo) . So 'name' in dir(Foo) is False for dataclasses. Is this a known behavior? dir(Foo) ['__annotations__', '__class__', '__dataclass_fields__', '__dataclass_params__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'bar'] dir(Foo(1, 2)) ['__annotations__', '__class__', '__dataclass_fields__', '__dataclass_params__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'bar', 'baz', 'name'] dir(create_autospec(Foo)) ['__annotations__', '__class__', '__dataclass_fields__', '__dataclass_params__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'assert_any_call', 'assert_called', 'assert_called_once', 'assert_called_once_with', 'assert_called_with', 'assert_has_calls', 'assert_not_called', 'attach_mock', 'bar', 'call_args', 'call_args_list', 'call_count', 'called', 'configure_mock', 'method_calls', 'mock_add_spec', 'mock_calls', 'reset_mock', 'return_value', 'side_effect'] print('name' in dir(fooMock)) # False print('baz' in dir(fooMock)) # False print('bar' in dir(fooMock)) # True [0] https://docs.python.org/3/library/unittest.mock.html#unittest.mock.create_autospec [1] https://github.com/python/cpython/blob/0e10766574f4e287cd6b5e5860a1ca75488f4119/Lib/unittest/mock.py#L2263 ---------- nosy: +xtreak _______________________________________ Python tracker <rep...@bugs.python.org> <https://bugs.python.org/issue36580> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com