Skip to content

Commit 38650c9

Browse files
committed
bpo-37555: Ensure all assert methods using _call_matcher are actually passing calls
1 parent f47699d commit 38650c9

File tree

1 file changed

+25
-9
lines changed

1 file changed

+25
-9
lines changed

Lib/unittest/mock.py

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -864,9 +864,9 @@ def assert_called_with(self, /, *args, **kwargs):
864864
def _error_message():
865865
msg = self._format_mock_failure_message(args, kwargs)
866866
return msg
867-
expected = self._call_matcher((args, kwargs))
867+
expected = self._call_matcher(_Call((args, kwargs)))
868868
actual = self._call_matcher(self.call_args)
869-
if expected != actual:
869+
if actual != expected:
870870
cause = expected if isinstance(expected, Exception) else None
871871
raise AssertionError(_error_message()) from cause
872872

@@ -926,10 +926,10 @@ def assert_any_call(self, /, *args, **kwargs):
926926
The assert passes if the mock has *ever* been called, unlike
927927
`assert_called_with` and `assert_called_once_with` that only pass if
928928
the call is the most recent one."""
929-
expected = self._call_matcher((args, kwargs))
929+
expected = self._call_matcher(_Call((args, kwargs), two=True))
930+
cause = expected if isinstance(expected, Exception) else None
930931
actual = [self._call_matcher(c) for c in self.call_args_list]
931-
if expected not in actual:
932-
cause = expected if isinstance(expected, Exception) else None
932+
if cause or expected not in _AnyComparer(actual):
933933
expected_string = self._format_mock_call_signature(args, kwargs)
934934
raise AssertionError(
935935
'%s call not found' % expected_string
@@ -982,6 +982,22 @@ def _calls_repr(self, prefix="Calls"):
982982
return f"\n{prefix}: {safe_repr(self.mock_calls)}."
983983

984984

985+
class _AnyComparer(list):
986+
"""A list which checks if it contains a call which may have an
987+
argument of ANY, flipping the components of item and self from
988+
their traditional locations so that ANY is guaranteed to be on
989+
the left."""
990+
def __contains__(self, item):
991+
for _call in self:
992+
if len(item) != len(_call):
993+
continue
994+
if all([
995+
expected == actual
996+
for expected, actual in zip(item, _call)
997+
]):
998+
return True
999+
return False
1000+
9851001

9861002
def _try_iter(obj):
9871003
if obj is None:
@@ -2133,9 +2149,9 @@ def _error_message():
21332149
msg = self._format_mock_failure_message(args, kwargs, action='await')
21342150
return msg
21352151

2136-
expected = self._call_matcher((args, kwargs))
2152+
expected = self._call_matcher(_Call((args, kwargs), two=True))
21372153
actual = self._call_matcher(self.await_args)
2138-
if expected != actual:
2154+
if actual != expected:
21392155
cause = expected if isinstance(expected, Exception) else None
21402156
raise AssertionError(_error_message()) from cause
21412157

@@ -2154,9 +2170,9 @@ def assert_any_await(self, /, *args, **kwargs):
21542170
"""
21552171
Assert the mock has ever been awaited with the specified arguments.
21562172
"""
2157-
expected = self._call_matcher((args, kwargs))
2173+
expected = self._call_matcher(_Call((args, kwargs), two=True))
21582174
actual = [self._call_matcher(c) for c in self.await_args_list]
2159-
if expected not in actual:
2175+
if expected not in _AnyComparer(actual):
21602176
cause = expected if isinstance(expected, Exception) else None
21612177
expected_string = self._format_mock_call_signature(args, kwargs)
21622178
raise AssertionError(

0 commit comments

Comments
 (0)