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

Reply via email to