aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Lib/test/test_unittest/testmock/testmock.py
diff options
context:
space:
mode:
authorinfohash <46137868+infohash@users.noreply.github.com>2024-03-09 00:44:32 +0530
committerGitHub <noreply@github.com>2024-03-08 19:14:32 +0000
commit735fc2cbbcf875c359021b5b2af7f4c29f4cf66d (patch)
tree1dabd0f3ea328367d4f0864f9b7c2e6ee86ecd2c /Lib/test/test_unittest/testmock/testmock.py
parent7db871e4fa48eef20ea22414b226998f83facfd6 (diff)
downloadcpython-735fc2cbbcf875c359021b5b2af7f4c29f4cf66d.tar.gz
cpython-735fc2cbbcf875c359021b5b2af7f4c29f4cf66d.zip
gh-75988: Fix issues with autospec ignoring wrapped object (#115223)
* set default return value of functional types as _mock_return_value * added test of wrapping child attributes * added backward compatibility with explicit return * added docs on the order of precedence * added test to check default return_value
Diffstat (limited to 'Lib/test/test_unittest/testmock/testmock.py')
-rw-r--r--Lib/test/test_unittest/testmock/testmock.py67
1 files changed, 67 insertions, 0 deletions
diff --git a/Lib/test/test_unittest/testmock/testmock.py b/Lib/test/test_unittest/testmock/testmock.py
index 1725406bcfb..b81b3049d56 100644
--- a/Lib/test/test_unittest/testmock/testmock.py
+++ b/Lib/test/test_unittest/testmock/testmock.py
@@ -245,6 +245,65 @@ class MockTest(unittest.TestCase):
with mock.patch('builtins.open', mock.mock_open()):
mock.mock_open() # should still be valid with open() mocked
+ def test_create_autospec_wraps_class(self):
+ """Autospec a class with wraps & test if the call is passed to the
+ wrapped object."""
+ result = "real result"
+
+ class Result:
+ def get_result(self):
+ return result
+ class_mock = create_autospec(spec=Result, wraps=Result)
+ # Have to reassign the return_value to DEFAULT to return the real
+ # result (actual instance of "Result") when the mock is called.
+ class_mock.return_value = mock.DEFAULT
+ self.assertEqual(class_mock().get_result(), result)
+ # Autospec should also wrap child attributes of parent.
+ self.assertEqual(class_mock.get_result._mock_wraps, Result.get_result)
+
+ def test_create_autospec_instance_wraps_class(self):
+ """Autospec a class instance with wraps & test if the call is passed
+ to the wrapped object."""
+ result = "real result"
+
+ class Result:
+ @staticmethod
+ def get_result():
+ """This is a static method because when the mocked instance of
+ 'Result' will call this method, it won't be able to consume
+ 'self' argument."""
+ return result
+ instance_mock = create_autospec(spec=Result, instance=True, wraps=Result)
+ # Have to reassign the return_value to DEFAULT to return the real
+ # result from "Result.get_result" when the mocked instance of "Result"
+ # calls "get_result".
+ instance_mock.get_result.return_value = mock.DEFAULT
+ self.assertEqual(instance_mock.get_result(), result)
+ # Autospec should also wrap child attributes of the instance.
+ self.assertEqual(instance_mock.get_result._mock_wraps, Result.get_result)
+
+ def test_create_autospec_wraps_function_type(self):
+ """Autospec a function or a method with wraps & test if the call is
+ passed to the wrapped object."""
+ result = "real result"
+
+ class Result:
+ def get_result(self):
+ return result
+ func_mock = create_autospec(spec=Result.get_result, wraps=Result.get_result)
+ self.assertEqual(func_mock(Result()), result)
+
+ def test_explicit_return_value_even_if_mock_wraps_object(self):
+ """If the mock has an explicit return_value set then calls are not
+ passed to the wrapped object and the return_value is returned instead.
+ """
+ def my_func():
+ return None
+ func_mock = create_autospec(spec=my_func, wraps=my_func)
+ return_value = "explicit return value"
+ func_mock.return_value = return_value
+ self.assertEqual(func_mock(), return_value)
+
def test_explicit_parent(self):
parent = Mock()
mock1 = Mock(parent=parent, return_value=None)
@@ -622,6 +681,14 @@ class MockTest(unittest.TestCase):
real = Mock()
mock = Mock(wraps=real)
+ # If "Mock" wraps an object, just accessing its
+ # "return_value" ("NonCallableMock.__get_return_value") should not
+ # trigger its descriptor ("NonCallableMock.__set_return_value") so
+ # the default "return_value" should always be "sentinel.DEFAULT".
+ self.assertEqual(mock.return_value, DEFAULT)
+ # It will not be "sentinel.DEFAULT" if the mock is not wrapping any
+ # object.
+ self.assertNotEqual(real.return_value, DEFAULT)
self.assertEqual(mock(), real())
real.reset_mock()