Mocking replaces a real dependency (a database call, an HTTP request, a file read) with a controlled fake. Your unit test then runs in isolation — fast, deterministic, no network required.
The Problem Without Mocking
def get_user_name(user_id: int) -> str:
row = database.query(f"SELECT name FROM users WHERE id={user_id}")
return row["name"]
def test_get_user_name():
# ❌ requires a running database with test data
assert get_user_name(1) == "Alice"unittest.mock.patch
from unittest.mock import patch, MagicMock
def test_get_user_name():
with patch("myapp.database.query") as mock_query:
mock_query.return_value = {"name": "Alice"}
result = get_user_name(1)
assert result == "Alice"
mock_query.assert_called_once_with("SELECT name FROM users WHERE id=1")patch replaces the target for the duration of the with block and restores the original afterwards.
pytest-mock (Cleaner Syntax)
pip install pytest-mockdef test_get_user_name(mocker):
mock_query = mocker.patch("myapp.database.query")
mock_query.return_value = {"name": "Alice"}
assert get_user_name(1) == "Alice"
mock_query.assert_called_once()The mocker fixture handles cleanup automatically — no with block needed.
Common Mock Assertions
mock.assert_called() # called at least once
mock.assert_called_once() # called exactly once
mock.assert_called_with(arg1, key=val) # called with specific args
mock.assert_not_called() # never called
# Inspect call history
print(mock.call_count) # number of calls
print(mock.call_args) # args of last call
print(mock.call_args_list) # args of all callsMocking HTTP Requests
import requests
def fetch_quote():
resp = requests.get("https://api.quotable.io/random")
return resp.json()["content"]
def test_fetch_quote(mocker):
mock_get = mocker.patch("requests.get")
mock_get.return_value.json.return_value = {"content": "Test quote"}
result = fetch_quote()
assert result == "Test quote"
mock_get.assert_called_once_with("https://api.quotable.io/random")Mock vs Real Dependency
Mock isolation visualiser
Ctrl+Enter
HTML
CSS
JS
Preview
MagicMock for Complex Objects
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = {"token": "abc123"}
# Supports context manager protocol
with patch("requests.post", return_value=mock_response) as mock_post:
token = login("alice", "pass")
assert token == "abc123"MagicMock supports magic methods (__enter__, __exit__, __len__, etc.) automatically.