Skip to content

Commit 891ee7e

Browse files
committed
Add original message from assert_* methods of the Mock object
1 parent 80eb9a1 commit 891ee7e

File tree

4 files changed

+82
-17
lines changed

4 files changed

+82
-17
lines changed

CHANGELOG.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
1.6.0
2+
-----
3+
4+
* The original assertions raised by the various ``Mock.assert_*`` methods
5+
now appear in the failure message, in addition to the message obtained from
6+
pytest introspection.
7+
Thanks `@quodlibetor`_ for the initial patch (`#79`_).
8+
9+
.. _@quodlibetor: https://github.com/quodlibetor
10+
11+
.. _#79: https://github.com/pytest-dev/pytest-mock/pull/79
12+
113
1.5.0
214
-----
315

README.rst

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -126,14 +126,30 @@ the method, and uses py.test's own `advanced assertions`_ to return a better
126126
diff::
127127

128128

129-
m = mocker.patch.object(DS, 'create_char')
130-
DS().create_char('Raistlin', class_='mag', gift=12)
131-
> m.assert_called_once_with('Raistlin', class_='mage', gift=12)
132-
E assert {'class_': 'mag', 'gift': 12} == {'class_': 'mage', 'gift': 12}
133-
E Omitting 1 identical items, use -v to show
134-
E Differing items:
135-
E {'class_': 'mag'} != {'class_': 'mage'}
129+
mocker = <pytest_mock.MockFixture object at 0x0381E2D0>
130+
131+
def test(mocker):
132+
m = mocker.Mock()
133+
m('fo')
134+
> m.assert_called_once_with('', bar=4)
135+
E AssertionError: Expected call: mock('', bar=4)
136+
E Actual call: mock('fo')
137+
E
138+
E pytest introspection follows:
139+
E
140+
E Args:
141+
E assert ('fo',) == ('',)
142+
E At index 0 diff: 'fo' != ''
136143
E Use -v to get the full diff
144+
E Kwargs:
145+
E assert {} == {'bar': 4}
146+
E Right contains more items:
147+
E {'bar': 4}
148+
E Use -v to get the full diff
149+
150+
151+
test_foo.py:6: AssertionError
152+
========================== 1 failed in 0.03 seconds ===========================
137153

138154

139155
This is useful when asserting mock calls with many/nested arguments and trying

pytest_mock.py

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import sys
33

44
import pytest
5+
56
from _pytest_mock_version import version
67

78
__version__ = version
@@ -172,18 +173,29 @@ def mock(mocker):
172173

173174
def assert_wrapper(__wrapped_mock_method__, *args, **kwargs):
174175
__tracebackhide__ = True
175-
err = None
176176
try:
177177
__wrapped_mock_method__(*args, **kwargs)
178+
return
178179
except AssertionError as e:
179-
__mock_self = args[0]
180-
if __mock_self.call_args is not None:
181-
actual_args, actual_kwargs = __mock_self.call_args
182-
assert actual_args == args[1:]
183-
assert actual_kwargs == kwargs
184-
err = e
185-
if err is not None:
186-
raise AssertionError(*err.args)
180+
if getattr(e, '_mock_introspection_applied', 0):
181+
msg = str(e)
182+
else:
183+
__mock_self = args[0]
184+
msg = str(e)
185+
if __mock_self.call_args is not None:
186+
actual_args, actual_kwargs = __mock_self.call_args
187+
msg += '\n\npytest introspection follows:\n'
188+
try:
189+
assert actual_args == args[1:]
190+
except AssertionError as e:
191+
msg += '\nArgs:\n' + str(e)
192+
try:
193+
assert actual_kwargs == kwargs
194+
except AssertionError as e:
195+
msg += '\nKwargs:\n' + str(e)
196+
e = AssertionError(msg)
197+
e._mock_introspection_applied = True
198+
raise e
187199

188200

189201
def wrap_assert_not_called(*args, **kwargs):

test_pytest_mock.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from contextlib import contextmanager
55

66
import py.code
7-
87
import pytest
98

109
pytest_plugins = 'pytester'
@@ -514,3 +513,29 @@ def runpytest_subprocess(testdir, *args):
514513
else:
515514
# pytest 2.7.X
516515
return testdir.runpytest(*args)
516+
517+
518+
def test_detailed_introspection(testdir):
519+
"""Check that the "mock_use_standalone" is being used.
520+
"""
521+
testdir.makepyfile("""
522+
def test(mocker):
523+
m = mocker.Mock()
524+
m('fo')
525+
m.assert_called_once_with('', bar=4)
526+
""")
527+
result = testdir.runpytest('-s')
528+
result.stdout.fnmatch_lines([
529+
"*AssertionError: Expected call: mock('', bar=4)*",
530+
"*Actual call: mock('fo')*",
531+
"*pytest introspection follows:*",
532+
'*Args:',
533+
"*assert ('fo',) == ('',)",
534+
"*At index 0 diff: 'fo' != ''*",
535+
"*Use -v to get the full diff*",
536+
"*Kwargs:*",
537+
"*assert {} == {'bar': 4}*",
538+
"*Right contains more items:*",
539+
"*{'bar': 4}*",
540+
"*Use -v to get the full diff*",
541+
])

0 commit comments

Comments
 (0)