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.
Using
mocker.spyon a function patched inside apytest.MonkeyPatch.context()ends up not undoing the patch on exiting the test function. Here's an example:With the
mocker.spyline commented out, both tests pass. Uncommenting it causes the patch to leak out oftest_patchand affecttest_normal:I did discover that
mocker.stopall()inside the MonkeyPatch context gets things working again, i.e. this seems to work: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.