summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2020-01-25 14:53:08 (GMT)
committerKarthikeyan Singaravelan <tir.karthi@gmail.com>2020-01-25 14:53:08 (GMT)
commita5906b2bfce9560568dee1dcc3550e74e742dd34 (patch)
treef9dabecd0a2793efcd729698bf8919875af39e71
parenta23449285430081ea317cc1f203c80c410bbd8b9 (diff)
downloadcpython-a5906b2bfce9560568dee1dcc3550e74e742dd34.zip
cpython-a5906b2bfce9560568dee1dcc3550e74e742dd34.tar.gz
cpython-a5906b2bfce9560568dee1dcc3550e74e742dd34.tar.bz2
bpo-38473: Handle autospecced functions and methods used with attach_mock (GH-16784) (GH-18167)
If an autospecced object is attached using attach_mock the child would be a function with mock object as attribute from which signature has to be derived. (cherry picked from commit 66b00a9d3aacf6ed49412f48743e4913104a2bb3) Co-authored-by: Karthikeyan Singaravelan <tir.karthi@gmail.com>
-rw-r--r--Lib/unittest/mock.py4
-rw-r--r--Lib/unittest/test/testmock/testmock.py29
-rw-r--r--Misc/NEWS.d/next/Library/2019-10-14-21-14-55.bpo-38473.uXpVld.rst2
3 files changed, 35 insertions, 0 deletions
diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py
index e92ccf1..34f2dd7 100644
--- a/Lib/unittest/mock.py
+++ b/Lib/unittest/mock.py
@@ -825,6 +825,10 @@ class NonCallableMock(Base):
if child is None or isinstance(child, _SpecState):
break
else:
+ # If an autospecced object is attached using attach_mock the
+ # child would be a function with mock object as attribute from
+ # which signature has to be derived.
+ child = _extract_mock(child)
children = child._mock_children
sig = child._spec_signature
diff --git a/Lib/unittest/test/testmock/testmock.py b/Lib/unittest/test/testmock/testmock.py
index 6dc2725..1cde45e 100644
--- a/Lib/unittest/test/testmock/testmock.py
+++ b/Lib/unittest/test/testmock/testmock.py
@@ -1914,6 +1914,35 @@ class MockTest(unittest.TestCase):
self.assertEqual(mock_func.mock._extract_mock_name(), 'mock.child')
+ def test_attach_mock_patch_autospec_signature(self):
+ with mock.patch(f'{__name__}.Something.meth', autospec=True) as mocked:
+ manager = Mock()
+ manager.attach_mock(mocked, 'attach_meth')
+ obj = Something()
+ obj.meth(1, 2, 3, d=4)
+ manager.assert_has_calls([call.attach_meth(mock.ANY, 1, 2, 3, d=4)])
+ obj.meth.assert_has_calls([call(mock.ANY, 1, 2, 3, d=4)])
+ mocked.assert_has_calls([call(mock.ANY, 1, 2, 3, d=4)])
+
+ with mock.patch(f'{__name__}.something', autospec=True) as mocked:
+ manager = Mock()
+ manager.attach_mock(mocked, 'attach_func')
+ something(1)
+ manager.assert_has_calls([call.attach_func(1)])
+ something.assert_has_calls([call(1)])
+ mocked.assert_has_calls([call(1)])
+
+ with mock.patch(f'{__name__}.Something', autospec=True) as mocked:
+ manager = Mock()
+ manager.attach_mock(mocked, 'attach_obj')
+ obj = Something()
+ obj.meth(1, 2, 3, d=4)
+ manager.assert_has_calls([call.attach_obj(),
+ call.attach_obj().meth(1, 2, 3, d=4)])
+ obj.meth.assert_has_calls([call(1, 2, 3, d=4)])
+ mocked.assert_has_calls([call(), call().meth(1, 2, 3, d=4)])
+
+
def test_attribute_deletion(self):
for mock in (Mock(), MagicMock(), NonCallableMagicMock(),
NonCallableMock()):
diff --git a/Misc/NEWS.d/next/Library/2019-10-14-21-14-55.bpo-38473.uXpVld.rst b/Misc/NEWS.d/next/Library/2019-10-14-21-14-55.bpo-38473.uXpVld.rst
new file mode 100644
index 0000000..de80e89
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2019-10-14-21-14-55.bpo-38473.uXpVld.rst
@@ -0,0 +1,2 @@
+Use signature from inner mock for autospecced methods attached with
+:func:`unittest.mock.attach_mock`. Patch by Karthikeyan Singaravelan.