diff options
author | Karthikeyan Singaravelan <tir.karthi@gmail.com> | 2020-01-24 13:14:29 (GMT) |
---|---|---|
committer | Chris Withers <chris@withers.org> | 2020-01-24 13:14:29 (GMT) |
commit | 66b00a9d3aacf6ed49412f48743e4913104a2bb3 (patch) | |
tree | 2326feba1f39e3613e1eae1fd9c5822591c2480a | |
parent | b8d1262e8afe7b907b4a394a191739571092acdb (diff) | |
download | cpython-66b00a9d3aacf6ed49412f48743e4913104a2bb3.zip cpython-66b00a9d3aacf6ed49412f48743e4913104a2bb3.tar.gz cpython-66b00a9d3aacf6ed49412f48743e4913104a2bb3.tar.bz2 |
bpo-38473: Handle autospecced functions and methods used with attach_mock (GH-16784)
-rw-r--r-- | Lib/unittest/mock.py | 4 | ||||
-rw-r--r-- | Lib/unittest/test/testmock/testmock.py | 29 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2019-10-14-21-14-55.bpo-38473.uXpVld.rst | 2 |
3 files changed, 35 insertions, 0 deletions
diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 3fafe59..92b596f 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -817,6 +817,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 01bc479..1030d12 100644 --- a/Lib/unittest/test/testmock/testmock.py +++ b/Lib/unittest/test/testmock/testmock.py @@ -1922,6 +1922,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. |