Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 28 additions & 8 deletions Lib/unittest/mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import sys
import builtins
from types import ModuleType
from unittest.util import safe_repr
from functools import wraps, partial


Expand Down Expand Up @@ -778,8 +779,10 @@ def assert_not_called(_mock_self):
"""
self = _mock_self
if self.call_count != 0:
msg = ("Expected '%s' to not have been called. Called %s times." %
(self._mock_name or 'mock', self.call_count))
msg = ("Expected '%s' to not have been called. Called %s times.%s"
% (self._mock_name or 'mock',
self.call_count,
self._calls_repr()))
raise AssertionError(msg)

def assert_called(_mock_self):
Expand All @@ -796,8 +799,10 @@ def assert_called_once(_mock_self):
"""
self = _mock_self
if not self.call_count == 1:
msg = ("Expected '%s' to have been called once. Called %s times." %
(self._mock_name or 'mock', self.call_count))
msg = ("Expected '%s' to have been called once. Called %s times.%s"
% (self._mock_name or 'mock',
self.call_count,
self._calls_repr()))
raise AssertionError(msg)

def assert_called_with(_mock_self, *args, **kwargs):
Expand Down Expand Up @@ -825,8 +830,10 @@ def assert_called_once_with(_mock_self, *args, **kwargs):
with the specified arguments."""
self = _mock_self
if not self.call_count == 1:
msg = ("Expected '%s' to be called once. Called %s times." %
(self._mock_name or 'mock', self.call_count))
msg = ("Expected '%s' to be called once. Called %s times.%s"
% (self._mock_name or 'mock',
self.call_count,
self._calls_repr()))
raise AssertionError(msg)
return self.assert_called_with(*args, **kwargs)

Expand All @@ -847,8 +854,8 @@ def assert_has_calls(self, calls, any_order=False):
if not any_order:
if expected not in all_calls:
raise AssertionError(
'Calls not found.\nExpected: %r\n'
'Actual: %r' % (_CallList(calls), self.mock_calls)
'Calls not found.\nExpected: %r%s'
% (_CallList(calls), self._calls_repr(prefix="Actual"))
) from cause
return

Expand Down Expand Up @@ -909,6 +916,19 @@ def _get_child_mock(self, **kw):
return klass(**kw)


def _calls_repr(self, prefix="Calls"):
"""Renders self.mock_calls as a string.

Example: "\nCalls: [call(1), call(2)]."

If self.mock_calls is empty, an empty string is returned. The
output will be truncated if very long.
"""
if not self.mock_calls:
return ""
return f"\n{prefix}: {safe_repr(self.mock_calls)}."



def _try_iter(obj):
if obj is None:
Expand Down
30 changes: 30 additions & 0 deletions Lib/unittest/test/testmock/testmock.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import copy
import re
import sys
import tempfile

Expand Down Expand Up @@ -407,6 +408,14 @@ def test_assert_called_once_with(self):
lambda: mock.assert_called_once_with('bob', 'bar', baz=2)
)

def test_assert_called_once_with_call_list(self):
m = Mock()
m(1)
m(2)
self.assertRaisesRegex(AssertionError,
re.escape("Calls: [call(1), call(2)]"),
lambda: m.assert_called_once_with(2))


def test_assert_called_once_with_function_spec(self):
def f(a, b, c, d=None):
Expand Down Expand Up @@ -1250,6 +1259,13 @@ def test_assert_not_called(self):
with self.assertRaises(AssertionError):
m.hello.assert_not_called()

def test_assert_not_called_message(self):
m = Mock()
m(1, 2)
self.assertRaisesRegex(AssertionError,
re.escape("Calls: [call(1, 2)]"),
m.assert_not_called)

def test_assert_called(self):
m = Mock()
with self.assertRaises(AssertionError):
Expand All @@ -1271,6 +1287,20 @@ def test_assert_called_once(self):
with self.assertRaises(AssertionError):
m.hello.assert_called_once()

def test_assert_called_once_message(self):
m = Mock()
m(1, 2)
m(3)
self.assertRaisesRegex(AssertionError,
re.escape("Calls: [call(1, 2), call(3)]"),
m.assert_called_once)

def test_assert_called_once_message_not_called(self):
m = Mock()
with self.assertRaises(AssertionError) as e:
m.assert_called_once()
self.assertNotIn("Calls:", str(e.exception))

#Issue21256 printout of keyword args should be in deterministic order
def test_sorted_call_signature(self):
m = Mock()
Expand Down
1 change: 1 addition & 0 deletions Misc/ACKS
Original file line number Diff line number Diff line change
Expand Up @@ -1570,6 +1570,7 @@ Daniel Stokes
Michael Stone
Serhiy Storchaka
Ken Stox
Petter Strandmark
Charalampos Stratakis
Dan Stromberg
Donald Stufft
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
``unittest.mock`` now includes mock calls in exception messages if
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: the change affects also assert_called_once_with and assert_has_calls

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert_has_calls was only refactored. Is it OK to write assert_called_once(_with)?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point!

About assert_called_once_with, I'd just list the three

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

``assert_not_called``, ``assert_called_once``, or ``assert_called_once_with``
fails. Patch by Petter Strandmark.