Testing a Database

    The current page still doesn’t have a translation for this language.

    But you can help translating it: Contributing.

    You can use the same dependency overrides from to alter a database for testing.

    You could want to set up a different database for testing, rollback the data after the tests, pre-fill it with some testing data, etc.

    The main idea is exactly the same you saw in that previous chapter.

    Let’s update the example from to use a testing database.

    All the app code is the same, you can go back to that chapter check how it was.

    The only changes here are in the new testing file.

    In the test, you could use a dependency override to return your custom database session instead of the one that would be used normally.

    In this example we’ll create a temporary database only for the tests.

    File structure

    We create a new file at sql_app/tests/test_sql_app.py.

    So the new file structure looks like:

    First, we create a new database session with the new database.

    For the tests we’ll use a file test.db instead of sql_app.db.

    But the rest of the session code is more or less the same, we just copy it.

    1. from fastapi.testclient import TestClient
    2. from sqlalchemy import create_engine
    3. from sqlalchemy.orm import sessionmaker
    4. from ..database import Base
    5. from ..main import app, get_db
    6. SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db"
    7. engine = create_engine(
    8. SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
    9. )
    10. TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
    11. Base.metadata.create_all(bind=engine)
    12. def override_get_db():
    13. try:
    14. db = TestingSessionLocal()
    15. yield db
    16. finally:
    17. db.close()
    18. app.dependency_overrides[get_db] = override_get_db
    19. client = TestClient(app)
    20. def test_create_user():
    21. response = client.post(
    22. "/users/",
    23. json={"email": "deadpool@example.com", "password": "chimichangas4life"},
    24. )
    25. assert response.status_code == 200, response.text
    26. data = response.json()
    27. assert data["email"] == "deadpool@example.com"
    28. assert "id" in data
    29. user_id = data["id"]
    30. assert response.status_code == 200, response.text
    31. data = response.json()
    32. assert data["email"] == "deadpool@example.com"
    33. assert data["id"] == user_id

    Tip

    For simplicity and to focus on the specific testing code, we are just copying it.

    Create the database

    Because now we are going to use a new database in a new file, we need to make sure we create the database with:

    That is normally called in main.py, but the line in main.py uses the database file sql_app.db, and we need to make sure we create test.db for the tests.

    So we add that line here, with the new file.

    1. from fastapi.testclient import TestClient
    2. from sqlalchemy import create_engine
    3. from sqlalchemy.orm import sessionmaker
    4. from ..database import Base
    5. from ..main import app, get_db
    6. SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db"
    7. engine = create_engine(
    8. SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
    9. )
    10. TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
    11. Base.metadata.create_all(bind=engine)
    12. def override_get_db():
    13. try:
    14. db = TestingSessionLocal()
    15. yield db
    16. finally:
    17. db.close()
    18. app.dependency_overrides[get_db] = override_get_db
    19. client = TestClient(app)
    20. def test_create_user():
    21. response = client.post(
    22. "/users/",
    23. json={"email": "deadpool@example.com", "password": "chimichangas4life"},
    24. )
    25. assert response.status_code == 200, response.text
    26. data = response.json()
    27. assert data["email"] == "deadpool@example.com"
    28. assert "id" in data
    29. user_id = data["id"]
    30. response = client.get(f"/users/{user_id}")
    31. assert response.status_code == 200, response.text
    32. assert data["email"] == "deadpool@example.com"
    33. assert data["id"] == user_id

    Now we create the dependency override and add it to the overrides for our app.

    Tip

    The code for is almost exactly the same as for get_db(), but in override_get_db() we use the TestingSessionLocal for the testing database instead.

    Test the app

    Then we can just test the app as normally.

    1. from fastapi.testclient import TestClient
    2. from sqlalchemy import create_engine
    3. from sqlalchemy.orm import sessionmaker
    4. from ..database import Base
    5. from ..main import app, get_db
    6. SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db"
    7. engine = create_engine(
    8. SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
    9. )
    10. TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
    11. Base.metadata.create_all(bind=engine)
    12. def override_get_db():
    13. try:
    14. db = TestingSessionLocal()
    15. yield db
    16. finally:
    17. db.close()
    18. app.dependency_overrides[get_db] = override_get_db
    19. client = TestClient(app)
    20. def test_create_user():
    21. response = client.post(
    22. "/users/",
    23. json={"email": "deadpool@example.com", "password": "chimichangas4life"},
    24. )
    25. assert response.status_code == 200, response.text
    26. data = response.json()
    27. assert data["email"] == "deadpool@example.com"
    28. assert "id" in data
    29. user_id = data["id"]
    30. response = client.get(f"/users/{user_id}")
    31. assert response.status_code == 200, response.text
    32. data = response.json()
    33. assert data["email"] == "deadpool@example.com"