How to Mock a Function Call in Python with unittest.mock

Use unittest.mock.Mock to wrap a function and spy on its call count and arguments in Python.

Easy Python 3.9+ Aug 9, 2026 Database scaling & optimization 14 views 0 copies

Python code

28 lines
Python 3.9+
import random
from unittest.mock import Mock, patch


def select_n_plus_one(numbers: list[int]) -> int:
    """Return the first number that appears more than once, if any."""
    seen = set()
    for num in numbers:
        if num in seen:
            return num
        seen.add(num)
    return -1


def detect_mock(select_func, numbers: list[int]) -> int:
    """Wrap a selector function with a mock to spy on calls."""
    mocked = Mock(wraps=select_func)
    result = mocked(numbers)
    print(f"Called {mocked.call_count} time(s)")
    print(f"Args: {mocked.call_args}")
    return result


if __name__ == "__main__":
    sample = [3, 1, 4, 1, 5, 9]
    selector = select_n_plus_one
    dup = detect_mock(selector, sample)
    print(f"Duplicate: {dup}")

Output

stdout
Called 1 time(s)
Args: call([3, 1, 4, 1, 5, 9])
Duplicate: 1

How it works

Mock(wraps=select_func) creates a mock that forwards calls to the original function while recording call metadata. The call_count attribute increments with each call, and call_args stores the arguments as a call object. Calling the mock executes the wrapped function and returns its result, so the actual logic still runs. This pattern is useful for testing without altering behavior, and the mock can also track multiple calls with call_args_list.

Common mistakes

  • Forgetting `wraps=` — without it, the mock returns a new Mock instead of the real function's result.
  • Using `assert_called_once()` on a mock that is called more than once, causing test failures.
  • Assuming `call_args` is a plain tuple — it's a `call` object that behaves like a tuple.
  • Not restoring the original function in tests if using `patch` instead of `wraps`.

Variations

  1. Use `patch('module.function')` to replace a function globally during a test.
  2. Use a custom spy class that records calls and still executes the original logic.

Real-world use cases

  • Verifying that a query function is called exactly once in a performance-critical database access path.
  • Recording arguments passed to an external API client while still making the actual network call in integration tests.
  • Instrumenting a production code path to measure call frequency without changing the function's behavior.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Database scaling & optimization

Related tutorials and quizzes for this topic.