0
0
PytestHow-ToBeginner ยท 4 min read

How to Use pytest-mock for Easy Mocking in Tests

Use pytest-mock by adding the mocker fixture to your test function. Call mocker.patch() to replace objects or functions with mocks during the test, allowing you to control behavior and assert calls.
๐Ÿ“

Syntax

The pytest-mock plugin provides a mocker fixture to your test functions. Use mocker.patch(target, **kwargs) to replace the target (a string path to the object) with a mock object. You can then configure the mock or check how it was called.

  • mocker.patch(target): Replaces the target with a mock.
  • target: The full import path of the object to mock, e.g., 'module.Class.method'.
  • kwargs: Optional arguments like return_value to set what the mock returns.
python
def test_example(mocker):
    mock_func = mocker.patch('module.function')
    mock_func.return_value = 42
    import module
    result = module.function()
    assert result == 42
    mock_func.assert_called_once()
๐Ÿ’ป

Example

This example shows how to mock a function in a module to control its return value and verify it was called once during the test.

python
import pytest

# Imagine this is in mymodule.py

def get_data():
    return 'real data'

def process_data():
    data = get_data()
    return f'Processed {data}'

# Test file

def test_process_data(mocker):
    mock_get = mocker.patch('mymodule.get_data', return_value='mocked data')
    from mymodule import process_data
    result = process_data()
    assert result == 'Processed mocked data'
    mock_get.assert_called_once()
Output
============================= test session starts ============================== collected 1 item test_example.py . [100%] ============================== 1 passed in 0.03s ===============================
โš ๏ธ

Common Pitfalls

Common mistakes include patching the wrong import path, forgetting to use the mocker fixture, or not asserting mock calls properly.

Always patch the object where it is used, not where it is defined. For example, if moduleA imports functionB from moduleB, patch moduleA.functionB, not moduleB.functionB.

python
import pytest

# Wrong patching - patching where function is defined, but test uses imported version

def test_wrong_patch(mocker):
    mocker.patch('moduleB.functionB', return_value=1)  # Wrong if test uses moduleA.functionB

# Right patching

def test_right_patch(mocker):
    mocker.patch('moduleA.functionB', return_value=1)  # Correct if test uses moduleA.functionB
๐Ÿ“Š

Quick Reference

  • mocker.patch(target, return_value=val): Replace target with mock returning val.
  • mock.assert_called_once(): Check mock was called exactly once.
  • mock.assert_not_called(): Check mock was never called.
  • mocker.spy(obj, 'method'): Spy on real method calls without replacing.
โœ…

Key Takeaways

Use the pytest-mock mocker fixture to patch objects easily in tests.
Always patch the object where it is used, not where it is defined.
Configure mock return values with return_value to control test behavior.
Assert mock calls with methods like assert_called_once() to verify interactions.
Use mocker.spy() to observe real method calls without replacing them.