12

When doing unit-testing with Python / PyTest, if you do you not have patch decorators or with patch blocks throughout your code, is there a way to reset all mocks at the end of every file / module to avoid inter-file test pollution?

It seems like something that is mocked in one Python test file remains mocked in other file with the same return value, which means my mocks are persisting between tests and files (when a patch decorator or with patch block is NOT used).

Is there any way around this other than patching? There wouldn't happen to be a mock.reset_all_mocks() or something like that, would there?

David A
  • 717
  • 1
  • 8
  • 18
  • How are you currently doing your mocking, and why? – jonrsharpe Oct 10 '15 at 07:07
  • 1
    I sometime do patching and sometimes I do something like `Module.method = MagicMock()`. The problem is that this mock persists across different files. Is there a way around that, so that it only persists within a single file/module? – David A Oct 11 '15 at 12:04
  • Just a note: for those who CAN use `patch`, it provides this exact behavior. From the docs: `The patch decorators are used for patching objects only within the scope of the function they decorate.` – Mike B Jun 11 '21 at 00:51

3 Answers3

11

What I ended up doing was using the pytest-mock library. According to the Readme:

This plugin installs a mocker fixture which is a thin-wrapper around the patching API provided by the excellent mock package, but with the benefit of not having to worry about undoing patches at the end of a test. (Emphasis added.)

So now I can do: mocker.patch.object(module, 'method', return_value='hi'), and the patch will be removed at the end of the test. There is no need to use with any more so that this solution scales nicely if you have many mocks in one test or if you want to change mocks during the test.

Lutz Prechelt
  • 36,608
  • 11
  • 63
  • 88
David A
  • 717
  • 1
  • 8
  • 18
5

After monkey-patching, I'm undoing it at the end of the test to avoid any leaking to other tests or limit the patching within the scope.

def test1(monkeypatch):
    monkeypatch.setattr(...)
    assert(...)
    monkeypatch.undo()
Luca Cappelletti
  • 2,485
  • 20
  • 35
Foreever
  • 7,099
  • 8
  • 53
  • 55
1

why don't use monkeypatch ?

The monkeypatch function argument helps you to safely set/delete an attribute, dictionary item or environment variable or to modify sys.path for importing.

you can:

def test1(monkeypatch):
    monkeypatch.setattr(.....
sax
  • 3,708
  • 19
  • 22