summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwookie184 <wookie1840@gmail.com>2024-01-04 19:11:34 (GMT)
committerGitHub <noreply@github.com>2024-01-04 19:11:34 (GMT)
commit1600d78e2d090319930c6538b496ffcca120a696 (patch)
tree2c3b626e673d9fc2ccd95df497d792a0241663fe
parent1ae7ceba29771baf8f2e8d2d4c50a0355cb6b5c8 (diff)
downloadcpython-1600d78e2d090319930c6538b496ffcca120a696.zip
cpython-1600d78e2d090319930c6538b496ffcca120a696.tar.gz
cpython-1600d78e2d090319930c6538b496ffcca120a696.tar.bz2
gh-113569: Display calls in Mock.assert_has_calls failure when empty (GH-113573)
-rw-r--r--Lib/test/test_unittest/testmock/testmock.py36
-rw-r--r--Lib/unittest/mock.py8
-rw-r--r--Misc/NEWS.d/next/Library/2023-12-29-17-57-45.gh-issue-113569.qcRCEI.rst2
3 files changed, 28 insertions, 18 deletions
diff --git a/Lib/test/test_unittest/testmock/testmock.py b/Lib/test/test_unittest/testmock/testmock.py
index 6af8acc..1725406 100644
--- a/Lib/test/test_unittest/testmock/testmock.py
+++ b/Lib/test/test_unittest/testmock/testmock.py
@@ -1547,25 +1547,33 @@ class MockTest(unittest.TestCase):
mock = Mock(spec=f)
mock(1)
- with self.assertRaisesRegex(
- AssertionError,
- '^{}$'.format(
- re.escape('Calls not found.\n'
- 'Expected: [call()]\n'
- ' Actual: [call(1)]'))) as cm:
+ with self.assertRaises(AssertionError) as cm:
mock.assert_has_calls([call()])
+ self.assertEqual(str(cm.exception),
+ 'Calls not found.\n'
+ 'Expected: [call()]\n'
+ ' Actual: [call(1)]'
+ )
self.assertIsNone(cm.exception.__cause__)
+ uncalled_mock = Mock()
+ with self.assertRaises(AssertionError) as cm:
+ uncalled_mock.assert_has_calls([call()])
+ self.assertEqual(str(cm.exception),
+ 'Calls not found.\n'
+ 'Expected: [call()]\n'
+ ' Actual: []'
+ )
+ self.assertIsNone(cm.exception.__cause__)
- with self.assertRaisesRegex(
- AssertionError,
- '^{}$'.format(
- re.escape(
- 'Error processing expected calls.\n'
- "Errors: [None, TypeError('too many positional arguments')]\n"
- "Expected: [call(), call(1, 2)]\n"
- ' Actual: [call(1)]'))) as cm:
+ with self.assertRaises(AssertionError) as cm:
mock.assert_has_calls([call(), call(1, 2)])
+ self.assertEqual(str(cm.exception),
+ 'Error processing expected calls.\n'
+ "Errors: [None, TypeError('too many positional arguments')]\n"
+ 'Expected: [call(), call(1, 2)]\n'
+ ' Actual: [call(1)]'
+ )
self.assertIsInstance(cm.exception.__cause__, TypeError)
def test_assert_any_call(self):
diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py
index 2adb3d7..93f4d97 100644
--- a/Lib/unittest/mock.py
+++ b/Lib/unittest/mock.py
@@ -1010,8 +1010,8 @@ class NonCallableMock(Base):
for e in expected])
raise AssertionError(
f'{problem}\n'
- f'Expected: {_CallList(calls)}'
- f'{self._calls_repr(prefix=" Actual").rstrip(".")}'
+ f'Expected: {_CallList(calls)}\n'
+ f' Actual: {safe_repr(self.mock_calls)}'
) from cause
return
@@ -1085,7 +1085,7 @@ class NonCallableMock(Base):
return klass(**kw)
- def _calls_repr(self, prefix="Calls"):
+ def _calls_repr(self):
"""Renders self.mock_calls as a string.
Example: "\nCalls: [call(1), call(2)]."
@@ -1095,7 +1095,7 @@ class NonCallableMock(Base):
"""
if not self.mock_calls:
return ""
- return f"\n{prefix}: {safe_repr(self.mock_calls)}."
+ return f"\nCalls: {safe_repr(self.mock_calls)}."
# Denylist for forbidden attribute names in safe mode
diff --git a/Misc/NEWS.d/next/Library/2023-12-29-17-57-45.gh-issue-113569.qcRCEI.rst b/Misc/NEWS.d/next/Library/2023-12-29-17-57-45.gh-issue-113569.qcRCEI.rst
new file mode 100644
index 0000000..9b63fc9
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-12-29-17-57-45.gh-issue-113569.qcRCEI.rst
@@ -0,0 +1,2 @@
+Indicate if there were no actual calls in unittest
+:meth:`~unittest.mock.Mock.assert_has_calls` failure.