Bird
Raised Fist0
FastAPIframework~5 mins

Testing with database in FastAPI

Choose your learning style10 modes available
Introduction

Testing with a database helps make sure your app works well when saving or reading data. It checks if your database code is correct and reliable.

When you want to check if your app saves user info correctly.
When you need to verify that data updates happen as expected.
When you want to test queries that fetch data from the database.
When you want to catch errors before your app goes live.
When you want to run automated tests that include database actions.
Syntax
FastAPI
from fastapi.testclient import TestClient
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from myapp.main import app, get_db
from myapp.database import Base

# Create a test database engine
SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})
TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

# Override the get_db dependency to use test DB
def override_get_db():
    db = TestingSessionLocal()
    try:
        yield db
    finally:
        db.close()

app.dependency_overrides[get_db] = override_get_db

client = TestClient(app)

Use a separate test database to avoid messing with real data.

Override the database dependency in FastAPI to use the test database during tests.

Examples
This test sends a POST request to create an item and checks if it was created correctly.
FastAPI
def test_create_item():
    response = client.post("/items/", json={"name": "Test Item"})
    assert response.status_code == 200
    assert response.json()["name"] == "Test Item"
This test fetches all items and checks if the response is a list.
FastAPI
def test_read_items():
    response = client.get("/items/")
    assert response.status_code == 200
    assert isinstance(response.json(), list)
Sample Program

This example shows a FastAPI app with a simple Item model and a POST endpoint to create items. It sets up a separate test database and overrides the database dependency for testing. The test sends a request to create an item and checks the response.

FastAPI
from fastapi import FastAPI, Depends
from fastapi.testclient import TestClient
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker, declarative_base, Session

SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()

class Item(Base):
    __tablename__ = "items"
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, index=True)

Base.metadata.create_all(bind=engine)

app = FastAPI()

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

@app.post("/items/")
def create_item(name: str, db: Session = Depends(get_db)):
    item = Item(name=name)
    db.add(item)
    db.commit()
    db.refresh(item)
    return {"id": item.id, "name": item.name}

# Testing setup
SQLALCHEMY_TEST_DATABASE_URL = "sqlite:///./test_test.db"
test_engine = create_engine(SQLALCHEMY_TEST_DATABASE_URL, connect_args={"check_same_thread": False})
TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=test_engine)
Base.metadata.create_all(bind=test_engine)

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_item():
    response = client.post("/items/", json={"name": "Test Item"})
    assert response.status_code == 200
    data = response.json()
    assert data["name"] == "Test Item"
    assert "id" in data

if __name__ == "__main__":
    test_create_item()
    print("Test passed")
OutputSuccess
Important Notes

Always use a separate database for tests to keep your real data safe.

Use FastAPI's dependency override feature to swap the database during tests.

Run tests often to catch bugs early.

Summary

Testing with a database helps verify your app's data handling.

Use a separate test database and override dependencies in FastAPI.

Write simple tests to check creating and reading data.

Practice

(1/5)
1. Why should you use a separate test database when testing FastAPI applications that interact with a database?
easy
A. To skip database setup during tests
B. To make tests run slower and more realistic
C. To avoid changing real data and keep tests isolated
D. To share data between tests and production

Solution

  1. Step 1: Understand test isolation

    Tests should not affect real data to avoid accidental data loss or corruption.
  2. Step 2: Use separate test database

    Using a separate database keeps test data separate and allows safe repeated testing.
  3. Final Answer:

    To avoid changing real data and keep tests isolated -> Option C
  4. Quick Check:

    Separate test database = safe isolated tests [OK]
Hint: Always isolate test data from real data [OK]
Common Mistakes:
  • Using production database for tests
  • Not cleaning test data after tests
  • Assuming tests don't affect real data
2. Which of the following is the correct way to override the database dependency in FastAPI tests?
easy
A. app.replace_dependency(get_db, override_get_db)
B. app.override_dependency(get_db, override_get_db)
C. app.set_dependency(get_db, override_get_db)
D. app.dependency_overrides[get_db] = override_get_db

Solution

  1. Step 1: Recall FastAPI dependency override syntax

    FastAPI uses the dictionary app.dependency_overrides to replace dependencies during tests.
  2. Step 2: Match correct syntax

    Assigning override_get_db function to app.dependency_overrides[get_db] is the correct method.
  3. Final Answer:

    app.dependency_overrides[get_db] = override_get_db -> Option D
  4. Quick Check:

    Override dependencies via app.dependency_overrides dict [OK]
Hint: Use app.dependency_overrides dictionary to override [OK]
Common Mistakes:
  • Using non-existent methods like set_dependency
  • Trying to override dependencies without assignment
  • Confusing syntax with other frameworks
3. Given this test code snippet, what will be the output of response.json()?
def test_create_item(client):
    response = client.post('/items/', json={'name': 'Book', 'price': 10})
    return response.json()
medium
A. {'id': 1, 'name': 'Book', 'price': 10}
B. {'name': 'Book', 'price': 10}
C. An error because POST is not allowed
D. Empty response {}

Solution

  1. Step 1: Understand POST /items/ behavior

    Assuming the endpoint creates an item and returns it with an assigned id.
  2. Step 2: Analyze response.json()

    The response should include the new item's id plus the sent data.
  3. Final Answer:

    {'id': 1, 'name': 'Book', 'price': 10} -> Option A
  4. Quick Check:

    POST creates item and returns it with id [OK]
Hint: POST usually returns created object with id [OK]
Common Mistakes:
  • Expecting only sent data without id
  • Assuming POST is disallowed
  • Ignoring response content
4. What is the main issue with this test code snippet?
def override_get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

app.dependency_overrides[get_db] = override_get_db

def test_read_items(client):
    response = client.get('/items/')
    assert response.status_code == 200
    assert response.json() == []
medium
A. The dependency override is missing
B. The test database session is not properly created or isolated
C. The test client is not defined
D. The test expects wrong status code

Solution

  1. Step 1: Check override_get_db function

    It uses SessionLocal but does not ensure a separate test database or transaction rollback.
  2. Step 2: Identify test isolation problem

    Without a test database or rollback, tests may affect real data or each other.
  3. Final Answer:

    The test database session is not properly created or isolated -> Option B
  4. Quick Check:

    Test DB session must be isolated and separate [OK]
Hint: Ensure test DB session is isolated and rolled back [OK]
Common Mistakes:
  • Not using a test database
  • Not overriding dependencies correctly
  • Assuming client is auto-defined
5. You want to write a test that creates an item, then reads it back from the test database in FastAPI. Which approach correctly ensures the test uses a separate database and cleans up after itself?
hard
A. Use a test database URL, override get_db to yield a session from it, and rollback after each test
B. Use the production database URL and delete created items manually after test
C. Use an in-memory list to mock database and skip actual DB calls
D. Run tests without overriding get_db and rely on default DB

Solution

  1. Step 1: Use separate test database URL

    This prevents tests from affecting production data.
  2. Step 2: Override get_db to yield test session and rollback

    This ensures each test runs isolated and cleans up changes automatically.
  3. Final Answer:

    Use a test database URL, override get_db to yield a session from it, and rollback after each test -> Option A
  4. Quick Check:

    Separate DB + override + rollback = clean isolated tests [OK]
Hint: Always isolate tests with separate DB and rollback [OK]
Common Mistakes:
  • Using production DB for tests
  • Not cleaning test data after tests
  • Skipping dependency overrides
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard