]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-38473: Handle autospecced functions and methods used with attach_mock (GH-16784...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Sat, 25 Jan 2020 14:54:57 +0000 (06:54 -0800)
committerKarthikeyan Singaravelan <tir.karthi@gmail.com>
Sat, 25 Jan 2020 14:54:57 +0000 (20:24 +0530)
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>
Lib/unittest/mock.py
Lib/unittest/test/testmock/testmock.py
Misc/NEWS.d/next/Library/2019-10-14-21-14-55.bpo-38473.uXpVld.rst [new file with mode: 0644]

index 213e596629965d39b005f7f695c7286ea54ec2bd..372a6719be9fa209133549d543d878732663102b 100644 (file)
@@ -794,6 +794,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
 
index 3046d4cfe639385ffab4ea84f38322ce08dc7bca..12772d39fcd99438dda24d2a46bae9a95f5982a0 100644 (file)
@@ -1863,6 +1863,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 (file)
index 0000000..de80e89
--- /dev/null
@@ -0,0 +1,2 @@
+Use signature from inner mock for autospecced methods attached with
+:func:`unittest.mock.attach_mock`. Patch by Karthikeyan Singaravelan.