
Mocking and Dependency Overrides
Isolate your tests. Learn how to replace real services (like databases and external APIs) with 'Fake' versions to make your tests fast and deterministic.
Mocking and Dependency Overrides
In the real world, your API might call an external service like Stripe or OpenAI. You don't want to spend real money or wait for the internet every time you run your tests.
In this lesson, we learn how to "Fake" these services using Mocking and FastAPI's powerful Dependency Overrides.
1. The Power of Dependency Overrides
We briefly saw this in Module 6. Because FastAPI uses Dependency Injection, we can swap out a real database connection for a fake one without touching our production code.
from main import app, get_db
# Create a fake database session
def override_get_db():
return TestingSessionLocal()
# Tell FastAPI to use the fake one for ALL tests in this file
app.dependency_overrides[get_db] = override_get_db
2. Mocking External APIs
If your route calls requests.get("https://stripe.com"), you can use the unittest.mock library to intercept that call and return a "Fake" response.
from unittest.mock import patch
@patch("app.services.stripe_client.charge")
def test_payment(mock_charge):
# Setup the mock to return "Success"
mock_charge.return_value = {"status": "paid"}
response = client.post("/buy", json={"amount": 100})
assert response.status_code == 200
3. Why Mocking is Essential
- Deterministic: Your tests don't fail just because the Stripe API is down.
- Speed: Calling a mock takes 0.1ms; calling a real API takes 1000ms.
- Edge Cases: You can force a mock to "Raise an Error" to see if your API handles failures correctly (e.g., "What happens if a user's card is declined?").
4. Test Fixtures
In Pytest, Fixtures are functions that run before your tests to "Set the Stage." You can create a fixture that resets your test database before every test.
import pytest
@pytest.fixture
def db_session():
# Setup
db = TestingSessionLocal()
yield db
# Teardown (Cleanup)
db.close()
Visualizing Mocking
graph LR
A["Test Runner"] --> B["FastAPI App"]
B --> C{Dependency?}
C -- "Production" --> D["Real Postgres / Real Stripe"]
C -- "Test Override" --> E["In-Memory SQLite / Mock Stripe"]
E --> F["Instant & Free Feedback"]
Summary
dependency_overrides: The #1 tool for swapping databases in tests.unittest.mock: The tool for faking external network calls.- Isolation: Good tests only check the logic of your code, not someone else's API.
- Fixtures: Use them for reusable setup and cleanup logic.
In the next lesson, we wrap up Module 14 with Exercises to test your testing skills.
Exercise: The Faker
You have a service that sends an SMS to a user. During tests, you want to ensure the SMS logic is called, but you don't want to send a real text.
- How would you use a mock to "Verify" that the
send_smsfunction was called exactly once? - Why is this called a "Behavior Test"?