0
0
PytestHow-ToBeginner ยท 4 min read

How to Mock Function in pytest: Simple Guide with Examples

To mock a function in pytest, use unittest.mock.patch as a decorator or context manager to replace the target function with a mock during the test. This lets you control the function's output and verify calls without running the real code.
๐Ÿ“

Syntax

The basic syntax to mock a function in pytest uses unittest.mock.patch. You specify the full path to the function you want to mock as a string. You can use it as a decorator or a context manager.

  • Decorator: Place @patch('module.function') above your test function.
  • Context manager: Use with patch('module.function') as mock_func: inside your test.

The mock object replaces the original function and can be configured to return values or check how it was called.

python
from unittest.mock import patch
import module

@patch('module.function_to_mock')
def test_example(mock_function):
    mock_function.return_value = 'mocked!'
    result = module.function_to_mock()
    assert result == 'mocked!'
๐Ÿ’ป

Example

This example shows how to mock a function get_data from a module data_source. The test replaces get_data with a mock that returns a fixed value, so the test does not depend on the real data source.

python
from unittest.mock import patch
import pytest

# Imagine this is in data_source.py
# def get_data():
#     return 'real data'

# Function under test
from data_source import get_data

def process_data():
    data = get_data()
    return data.upper()

@patch('data_source.get_data')
def test_process_data(mock_get_data):
    mock_get_data.return_value = 'mocked data'
    result = process_data()
    assert result == 'MOCKED DATA'
โš ๏ธ

Common Pitfalls

Common mistakes when mocking functions in pytest include:

  • Mocking the wrong import path. Always mock the function where it is used, not where it is defined.
  • Not setting return_value or side effects, causing the mock to return MagicMock objects instead of expected values.
  • Forgetting to use @patch or with patch(), so the real function runs and tests become slow or flaky.
python
from unittest.mock import patch

# Wrong: mocking the function where it is defined, not where used
@patch('data_source.get_data')  # Correct if process_data imports get_data from data_source

def test_wrong_path(mock_get_data):
    mock_get_data.return_value = 'mocked'
    # If process_data imports get_data differently, this mock won't work

# Right: mock where the function is used
@patch('module_where_process_data_uses_get_data.get_data')
def test_right_path(mock_get_data):
    mock_get_data.return_value = 'mocked'
    # This mock works correctly
๐Ÿ“Š

Quick Reference

Tips for mocking functions in pytest:

  • Use unittest.mock.patch to replace functions during tests.
  • Always mock the function where it is imported and used, not where it is defined.
  • Set return_value or side_effect on the mock to control behavior.
  • Use @patch decorator for simple cases or with patch() for scoped mocking.
  • Check mock calls with mock_function.assert_called_once() or similar assertions.
โœ…

Key Takeaways

Use unittest.mock.patch to replace functions in pytest tests.
Mock the function where it is used, not where it is defined.
Set return_value on the mock to control its output.
Use @patch decorator or with patch() context manager as needed.
Verify mock calls with assertions like assert_called_once.