Skip to content
Open
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
5 changes: 5 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Releases
========

UNRELEASED
----------

* `#650 <https://github.com/pytest-dev/pytest-mock/pull/650>`_: Entering a mock created by ``mocker.patch`` as a context manager now returns its ``__enter__.return_value`` instead of always ``None``, while still issuing the warning about using mocks as context managers.

3.17.0
------

Expand Down
22 changes: 14 additions & 8 deletions src/pytest_mock/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,14 +312,20 @@ def _start_patch(
# check if `mocked` is actually a mock object, as depending on autospec or target
# parameters `mocked` can be anything
if hasattr(mocked, "__enter__") and warn_on_mock_enter:
mocked.__enter__.side_effect = lambda: warnings.warn(
"Mocks returned by pytest-mock do not need to be used as context managers. "
"The mocker fixture automatically undoes mocking at the end of a test. "
"This warning can be ignored if it was triggered by mocking a context manager. "
"https://pytest-mock.readthedocs.io/en/latest/usage.html#usage-as-context-manager",
PytestMockWarning,
stacklevel=5,
)

def warn_on_enter() -> Any:
warnings.warn(
"Mocks returned by pytest-mock do not need to be used as context managers. "
"The mocker fixture automatically undoes mocking at the end of a test. "
"This warning can be ignored if it was triggered by mocking a context manager. "
"https://pytest-mock.readthedocs.io/en/latest/usage.html#usage-as-context-manager",
PytestMockWarning,
stacklevel=5,
)
# Let the mock return its ``return_value`` as usual.
return self.mock_module.DEFAULT

mocked.__enter__.side_effect = warn_on_enter
return mocked

def object(
Expand Down
17 changes: 17 additions & 0 deletions tests/test_pytest_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -1837,6 +1837,23 @@ def my_func():
mocker.patch.object(dummy_module, "MyContext")
assert isinstance(my_func(), mocker.MagicMock)

def test_patching_a_context_manager_object(self, mocker: MockerFixture) -> None:
"""The warning should not change what entering the patched object returns."""

class dummy_module:
pool: Any = None

pool = mocker.patch.object(dummy_module, "pool")
with pytest.warns(PytestMockWarning), dummy_module.pool as entered:
pass
assert entered is pool.__enter__.return_value

connection = object()
pool.__enter__.return_value = connection
with pytest.warns(PytestMockWarning), dummy_module.pool as entered:
pass
assert entered is connection

def test_patch_context_manager(self, mocker: MockerFixture) -> None:
"""Test that no warnings are issued when an object patched with
patch.context_manager is used as a context manager (#221)"""
Expand Down