
Dependency Chains and Overrides
Master the advanced side of DI. Learn how to nest dependencies and how to override them for seamless automated testing.
Dependency Chains and Overrides
FastAPI's Dependency Injection system isn't just flat; it's a Graph. Dependencies can themselves depend on other dependencies. This allows you to build complex, layered logic while keeping each piece of code tiny and focused.
In this lesson, we explore nested dependencies and the power of testing overrides.
1. Nested Dependencies (Chains)
Imagine you want to check if a user is an Admin.
- The
check_admindependency depends on... - The
get_current_userdependency, which depends on... - The
get_tokendependency.
FastAPI will resolve this entire tree automatically.
async def get_current_user(token: str = Depends(get_token)):
user = db.find_user(token)
return user
async def check_admin(user: User = Depends(get_current_user)):
if not user.is_admin:
raise HTTPException(status_code=403, detail="Admins only")
return user
@app.get("/admin-panel")
def read_admin(admin: User = Depends(check_admin)):
return {"message": f"Welcome, Admin {admin.username}"}
2. Dependency Overrides (The Testing Secret)
This is arguably the most powerful feature for production apps. When you are running automated tests, you don't want to connect to your real database or send real emails.
FastAPI allows you to Override any dependency in your app.dependency_overrides dictionary.
# In your test file:
def get_fake_db():
return MockDatabase()
# Tell the app to use the fake DB instead of the real one!
app.dependency_overrides[get_db] = get_fake_db
# Run your tests...
# After tests, clear the overrides
app.dependency_overrides = {}
3. Sub-dependencies with Parameters
You can create dependencies that are actually Classes. This allows you to pass parameters to the dependency itself.
class SearchSettings:
def __init__(self, q: str | None = None, limit: int = 10):
self.q = q
self.limit = limit
@app.get("/items/")
async def read_items(search: SearchSettings = Depends(SearchSettings)):
return {"query": search.q, "limit": search.limit}
4. Cache and Singleton Patterns
FastAPI correctly handles dependencies that are used multiple times in the same request. If Dependency A is required by both Dependency B and your Endpoint, FastAPI will only run Dependency A once and share the result (cache).
Visualizing the Graph
graph TD
A["Request"] --> B["Admin Check"]
B --> C["User Check"]
C --> D["Token Extraction"]
D --> E["Header Parsing"]
E & D & C & B --> F["Final Endpoint Function"]
Summary
- Deep Chains: FastAPI handles the "Nesting" so you don't have to.
- Overrides: The foundation of robust, isolated automated testing.
- Class Dependencies: Use
__init__to create reusable logic with parameters. - Efficiency: Results are cached within a single request context.
In the next lesson, we wrap up Module 6 with Exercises to test your dependency injection logic.
Exercise: The Chain Architect
Design a chain for a Subscription Service:
get_user: Fetches a user from a database.get_subscription: Depends onget_userand checks if they have an active plan.require_pro_plan: Depends onget_subscriptionand raises an error if the plan is not "Pro".
How would you use require_pro_plan on a VIP endpoint?