Karthikeyan Singaravelan <[email protected]> added the comment:
@guboi72 is right that signature for class constructor is used also for
methods. Another possible solution would be that mock stores it's children in
_mock_children dictionary so when a method is called then name can be used to
get the relevant child mock which would have the signature set that can be used.
In the below program call().foo also uses the signature (a, b) of __init__ and
in the call_matcher check name "foo" can be used to get the child mock from
mock_class._mock_children that will have the signature set during
create_autospec. This will give the signature (a) but it's little difficult to
construct the name. It also needs to handle cases for inner classes like
Foo.Bar.foo() where Bar is an inner class inside Foo.
from unittest.mock import *
class Foo:
def __init__(self, a, b):
pass
def foo(self, a):
pass
mock_class = create_autospec(Foo)
mock = mock_class(1, 2)
mock.foo(1)
print(mock_class._mock_children)
print(mock._mock_children)
mock_class.assert_has_calls([call(1, 2), call().foo(1)])
mock.assert_has_calls([call.foo(1)])
$ python3.7 ../backups/unittest_mock_spec_conflict.py
{'foo': <MagicMock name='mock.foo' spec='function' id='4534528096'>}
{'foo': <MagicMock name='mock().foo' spec='function' id='4534099584'>}
Traceback (most recent call last):
File "../backups/unittest_mock_spec_conflict.py", line 17, in <module>
mock_class.assert_has_calls([call(1, 2), call().foo(1)])
File
"/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/mock.py",
line 852, in assert_has_calls
) from cause
AssertionError: Calls not found.
Expected: [call(1, 2), call().foo(1)]
Actual: [call(1, 2), call().foo(1)]
A very rough hack that fixes the above case and explains my approach but not so
robust.
diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py
index 2ccf0d82ce..f0e917d57e 100644
--- a/Lib/unittest/mock.py
+++ b/Lib/unittest/mock.py
@@ -777,7 +777,17 @@ class NonCallableMock(Base):
else:
name, args, kwargs = _call
try:
- return name, sig.bind(*args, **kwargs)
+ if name:
+ if name.startswith("()"):
+ mock_name = "mock" + name # Handle call().foo where
name is ().foo
+ else:
+ mock_name = "mock." + name # Handle call.foo where
name is foo
+ sig = self._mock_children.get(mock_name)
+
+ if sig:
+ return name, sig.bind(*args, **kwargs)
+ else:
+ return _call
except TypeError as e:
return e.with_traceback(None)
else:
----------
nosy: +cjw296, mariocj89
versions: +Python 3.7, Python 3.8 -Python 3.6
_______________________________________
Python tracker <[email protected]>
<https://bugs.python.org/issue26752>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com