From 24bce30e02376a861399ba1250a2709e05d34b2d Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 25 Mar 2019 07:54:18 -0300 Subject: [PATCH] Fix RuntimeError if user code calls patcher.stopall Fix #137 --- CHANGELOG.rst | 9 +++++++++ pytest_mock.py | 12 +++++++++++- test_pytest_mock.py | 21 +++++++++++++++++++++ tox.ini | 3 +++ 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 47361c9..26e239e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,3 +1,12 @@ +1.10.2 +------ + +* Fix bug at the end of the test session when a call to ``patch.stopall`` is done explicitly by + user code. Thanks `@craiga`_ for the report (`#137`_). + +.. _#137: https://github.com/pytest-dev/pytest-mock/issues/137 +.. _@craiga: https://github.com/craiga + 1.10.1 ------ diff --git a/pytest_mock.py b/pytest_mock.py index cf1fd6f..8647e1a 100644 --- a/pytest_mock.py +++ b/pytest_mock.py @@ -288,7 +288,17 @@ def wrap_assert_methods(config): def unwrap_assert_methods(): for patcher in _mock_module_patches: - patcher.stop() + try: + patcher.stop() + except RuntimeError as e: + # a patcher might have been stopped by user code (#137) + # so we need to catch this error here and ignore it; + # unfortunately there's no public API to check if a patch + # has been started, so catching the error it is + if text_type(e) == "stop called on unstarted patcher": + pass + else: + raise _mock_module_patches[:] = [] _mock_module_originals.clear() diff --git a/test_pytest_mock.py b/test_pytest_mock.py index b4368ff..1cb3889 100644 --- a/test_pytest_mock.py +++ b/test_pytest_mock.py @@ -610,3 +610,24 @@ def test_assert_called_with_unicode_arguments(mocker): with pytest.raises(AssertionError): stub.assert_called_with(u"lak") + + +def test_plain_stopall(testdir): + """Calling patch.stopall() in a test would cause an error during unconfigure (#137)""" + testdir.makepyfile( + """ + import random + + def get_random_number(): + return random.randint(0, 100) + + def test_get_random_number(mocker): + patcher = mocker.mock_module.patch("random.randint", lambda x, y: 5) + patcher.start() + assert get_random_number() == 5 + mocker.mock_module.patch.stopall() + """ + ) + result = testdir.runpytest_subprocess() + result.stdout.fnmatch_lines("* 1 passed in *") + assert "RuntimeError" not in result.stderr.str() diff --git a/tox.ini b/tox.ini index c190e8d..e0efa9c 100644 --- a/tox.ini +++ b/tox.ini @@ -18,3 +18,6 @@ usedevelop = True extras = dev basepython = python3.6 commands = pre-commit run --all-files --show-diff-on-failure + +[pytest] +addopts = -ra