pytest-mock vs unittest.mock: Simplifying Mocking in Python Tests

Traditional mocking with unittest.mock often requires repetitive setup and teardown code, which can make test code harder to read and maintain.

pytest-mock addresses this issue by leveraging pytest’s fixture system, simplifying the mocking process and reducing boilerplate code.

Consider the following example that demonstrates the difference between unittest.mock and pytest-mock.

Using unittest.mock:

%%writefile test_rm_file.py
from unittest.mock import patch
import os


def rm_file(filename):
    os.remove(filename)


def test_with_unittest_mock():
    with patch("os.remove") as mock_remove:
        rm_file("file")
        mock_remove.assert_called_once_with("file")

Using pytest-mock:

%%writefile test_rm_file.py
import os


def rm_file(filename):
    os.remove(filename)


def test_unix_fs(mocker):
    mocker.patch("os.remove")
    rm_file("file")
    os.remove.assert_called_once_with("file")

Key differences:

  1. Setup: pytest-mock uses the mocker fixture, automatically provided by pytest, eliminating the need to import patching utilities.
  2. Patching: With pytest-mock, you simply call mocker.patch('os.remove'), whereas unittest.mock requires a context manager or decorator.
  3. Cleanup: pytest-mock automatically undoes mocking after the test, while unittest.mock relies on the context manager for cleanup.
  4. Accessing mocks: pytest-mock allows direct access to the patched function (e.g., os.remove.assert_called_once_with()), while unittest.mock requires accessing the mock through a variable (e.g., mock_remove.assert_called_once_with()).

Link to pytest-mock.

Scroll to Top

Work with Khuyen Tran

Work with Khuyen Tran