Skip to content

Commit

Permalink
Raise an error if mocker is used in a with context (#165)
Browse files Browse the repository at this point in the history
Raise an error if mocker is used in a `with` context
  • Loading branch information
nicoddemus committed Oct 23, 2019
2 parents 93b7ae3 + dcfc8ba commit 19a4e4d
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 1 deletion.
7 changes: 6 additions & 1 deletion CHANGELOG.rst
@@ -1,11 +1,16 @@
1.11.2 (unreleased)
1.11.2 (2019-10-19)
-------------------

* The *pytest introspection follows* message is no longer shown
if there is no pytest introspection (`#154`_).
Thanks `@The-Compiler`_ for the report.

* ``mocker`` now raises a ``TypeError`` when used as a context-manager.
Thanks `@binarymason`_ for the PR (`#165`_).

.. _#154: https://github.com/pytest-dev/pytest-mock/issues/154
.. _#165: https://github.com/pytest-dev/pytest-mock/pull/165
.. _@binarymason: https://github.com/binarymason

1.11.1 (2019-10-04)
-------------------
Expand Down
14 changes: 14 additions & 0 deletions src/pytest_mock/plugin.py
Expand Up @@ -156,8 +156,22 @@ def _start_patch(self, mock_func, *args, **kwargs):

def object(self, *args, **kwargs):
"""API to mock.patch.object"""
self._enforce_no_with_context(inspect.stack())
return self._start_patch(self.mock_module.patch.object, *args, **kwargs)

def _enforce_no_with_context(self, stack):
"""raises a ValueError if mocker is used in a with context"""
caller = stack[1]
frame = caller[0]
info = inspect.getframeinfo(frame)
code_context = " ".join(info.code_context).strip()

if code_context.startswith("with mocker."):
raise ValueError(
"Using mocker in a with context is not supported. "
"https://github.com/pytest-dev/pytest-mock#note-about-usage-as-context-manager"
)

def multiple(self, *args, **kwargs):
"""API to mock.patch.multiple"""
return self._start_patch(self.mock_module.patch.multiple, *args, **kwargs)
Expand Down
19 changes: 19 additions & 0 deletions tests/test_pytest_mock.py
Expand Up @@ -721,3 +721,22 @@ def test_get_random_number(mocker):
result = testdir.runpytest_subprocess()
result.stdout.fnmatch_lines("* 1 passed in *")
assert "RuntimeError" not in result.stderr.str()


def test_abort_context_manager(mocker):
class A(object):
def doIt(self):
return False

a = A()

with pytest.raises(ValueError) as excinfo:
with mocker.patch.object(a, "doIt", return_value=True):
assert a.doIt() == True

expected_error_msg = (
"Using mocker in a with context is not supported. "
"https://github.com/pytest-dev/pytest-mock#note-about-usage-as-context-manager"
)

assert str(excinfo.value) == expected_error_msg

0 comments on commit 19a4e4d

Please sign in to comment.