Closed
Description
Using mocker.spy
on a function patched inside a pytest.MonkeyPatch.context()
ends up not undoing the patch on exiting the test function. Here's an example:
import pytest
class SomeClass:
@staticmethod
def outer(arg):
return "outer says (" + SomeClass.inner(arg) + ")"
@staticmethod
def inner(arg):
return "inner says (" + arg + ")"
def test_patch(mocker):
def patched(arg):
return "patched says (" + arg + ")"
with pytest.MonkeyPatch.context() as mp:
mp.setattr(SomeClass, 'inner', patched)
#spy = mocker.spy(SomeClass, 'inner')
assert SomeClass.outer('foo') == 'outer says (patched says (foo))'
def test_normal():
assert SomeClass.outer('foo') == 'outer says (inner says (foo))'
With the mocker.spy
line commented out, both tests pass. Uncommenting it causes the patch to leak out of test_patch
and affect test_normal
:
def test_normal():
> assert SomeClass.outer('foo') == 'outer says (inner says (foo))'
E AssertionError: assert 'outer says (...d says (foo))' == 'outer says (...r says (foo))'
E - outer says (inner says (foo))
E ? ^^^ ^
E + outer says (patched says (foo))
E ? ^^^^^ ^
test_mod.py:24: AssertionError
I did discover that mocker.stopall()
inside the MonkeyPatch context gets things working again, i.e. this seems to work:
with pytest.MonkeyPatch.context() as mp:
mp.setattr(SomeClass, 'inner', patched)
spy = mocker.spy(SomeClass, 'inner')
assert SomeClass.outer('foo') == 'outer says (patched says (foo))'
mocker.stopall()
I think I expected all patches and spies to magically undo themselves without me needing to call mocker.stopall()
myself. Maybe mixing these magics together is not allowed?
For reference, I'm using pytest 7.1.1, pytest-mock 3.7.0, and python 3.9.12.
Metadata
Metadata
Assignees
Labels
No labels