Custom Dependency Classes in FastAPI: Cleaner and More Reusable Code

As FastAPI projects grow, code organization and reusability become increasingly important. While FastAPI’s dependency injection system is very flexible, you’ve probably noticed that many dependencies are simple functions. But did you know you can write dependency classes, too? In this article, I’ll show you how and why to use classes as dependencies for cleaner, testable, and more modular code.

Why Use Classes for Dependencies?

Dependency functions are quick to write but can get unwieldy as logic grows. With classes, your dependencies can:

  • Bundle related logic and state
  • Support configuration via __init__
  • Implement more complex patterns like context managers (for resource management)
  • Make code more readable and testable

Basic Example: Dependency as a Class

Suppose you want a dependency that gets the current user from a JWT token and caches some computation across multiple dependency-injected calls in a single request.

from fastapi import Depends, HTTPException, Request

class UserDependency:
    def __init__(self, request: Request):
        self.request = request
        self._user = None  # Cache

    async def __call__(self):
        if self._user is not None:
            return self._user
        token = self.request.headers.get("Authorization")
        if not token:
            raise HTTPException(status_code=401, detail="No token provided.")
        # ...parse and validate token, fetch user...
        self._user = {"username": "fasteddy"}  # Dummy user
        return self._user

You can inject this class just like a function dependency:

@app.get("/me")
async def read_current_user(current_user=Depends(UserDependency)):
    return current_user

When to Use Classes

  • Dependencies with internal state or caching
  • Sharing information/context between dependencies
  • Implementing context managers (with __enter__/__exit__ or __aenter__/__aexit__)
  • Grouping related dependency logic and helper methods

Pro Tip: Dependency Classes Make Testing Easier

By using classes, you can mock dependencies more easily in your test suite:

from starlette.testclient import TestClient
class MockUserDependency:
    async def __call__(self):
        return {"username": "testuser"}
app.dependency_overrides[UserDependency] = MockUserDependency

Conclusion

Using classes as dependencies is a powerful design pattern in FastAPI that increases your code’s modularity and testability. Take a small refactor step today—your future refactoring-self will thank you.

Have you tried this pattern in your FastAPI code? Let me know on the site or in the comments!

— Fast Eddy

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *