Mocking HTTP and Time (Deterministic Tests)
On this page
Principle
Unit tests should not depend on real network or real time. Mock at boundaries and keep core logic pure.
Mocking an HTTP Client via DI
from unittest.mock import Mock
def fetch_user(client, user_id: int) -> dict:
return client.get(f"/users/{user_id}")
def test_fetch_user():
client = Mock()
client.get.return_value = {"id": 1}
out = fetch_user(client, 1)
assert out["id"] == 1
client.get.assert_called_once_with("/users/1")
Controlling Time
class FakeClock:
def __init__(self, now_iso: str) -> None:
self._now_iso = now_iso
def now(self) -> str:
return self._now_iso
Operational Checklist
- Prefer dependency injection over patching globals.
- Do not mock your own code; mock external I/O.
- Make retries/timeouts testable by injecting clock/sleep functions.
Failure Modes
- Flaky tests: real network/time introduces nondeterminism.
- Mock drift: mocks stop matching real dependency behavior.