How to Mock Database in FastAPI Test: Simple Guide
To mock a database in
FastAPI tests, override the database dependency with a test version using app.dependency_overrides. Use an in-memory SQLite database or mock objects to simulate database behavior without affecting the real database.Syntax
In FastAPI, you mock the database by overriding the dependency that provides the database session. This is done by assigning a test function to app.dependency_overrides[original_dependency]. The test function returns a test database session, often an in-memory SQLite session.
app.dependency_overrides: A dictionary to replace dependencies during tests.get_db: The original dependency that yields a database session.override_get_db: Your test function that yields a test database session.
python
from fastapi import FastAPI, Depends from sqlalchemy.orm import Session app = FastAPI() def get_db(): # Original database session provider db = Session() try: yield db finally: db.close() # In tests: def override_get_db(): test_db = Session() # Use test database session here try: yield test_db finally: test_db.close() app.dependency_overrides[get_db] = override_get_db
Example
This example shows how to mock the database in a FastAPI test using an in-memory SQLite database. It overrides the get_db dependency to use the test database, then runs a test client request to verify the mocked database works.
python
from fastapi import FastAPI, Depends from fastapi.testclient import TestClient from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker, Session from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String app = FastAPI() SQLALCHEMY_DATABASE_URL = "sqlite:///:memory:" engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}) TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) Base = declarative_base() class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, index=True) name = Column(String, index=True) Base.metadata.create_all(bind=engine) def get_db(): db = TestingSessionLocal() try: yield db finally: db.close() @app.post("/users/") def create_user(name: str, db: Session = Depends(get_db)): user = User(name=name) db.add(user) db.commit() db.refresh(user) return {"id": user.id, "name": user.name} # Override dependency for tests def override_get_db(): db = TestingSessionLocal() try: yield db finally: db.close() app.dependency_overrides[get_db] = override_get_db client = TestClient(app) def test_create_user(): response = client.post("/users/", params={"name": "Alice"}) assert response.status_code == 200 assert response.json()["name"] == "Alice"
Output
PASSED
Common Pitfalls
- Not overriding the dependency: Tests may hit the real database, causing side effects.
- Using a persistent database for tests: This can cause flaky tests and data pollution.
- Forgetting to close test sessions: Can lead to connection leaks.
- Not creating tables in the test database: Leads to errors when querying.
python
## Wrong way: Not overriding dependency # This hits the real database # Right way: Override dependency with test DB app.dependency_overrides[get_db] = override_get_db
Quick Reference
- Use
app.dependency_overridesto replaceget_dbwith a test version. - Use an in-memory SQLite database for fast, isolated tests.
- Always create tables in the test database before running tests.
- Close test database sessions properly to avoid leaks.
- Use
fastapi.testclient.TestClientto run API tests with mocked DB.
Key Takeaways
Always override the database dependency in FastAPI tests to avoid using the real database.
Use an in-memory SQLite database for fast and isolated test runs.
Create all necessary tables in the test database before running tests.
Close database sessions properly in your test overrides to prevent connection leaks.
Use FastAPI's TestClient to test endpoints with the mocked database.