Documented testing approach does not work for SQLite in-memory instances
See original GitHub issueFirst Check
- I added a very descriptive title to this issue.
- I used the GitHub search to find a similar issue and didn’t find it.
- I searched the FastAPI documentation, with the integrated search.
- I already searched in Google “How to X in FastAPI” and didn’t find any information.
- I already read and followed all the tutorial in the docs and didn’t find an answer.
- I already checked if it is not related to FastAPI but to Pydantic.
- I already checked if it is not related to FastAPI but to Swagger UI.
- I already checked if it is not related to FastAPI but to ReDoc.
Commit to Help
- I commit to help with one of those options 👆
Example Code
# ----------------------------------------------------------------
# app.py
from __future__ import annotations
from fastapi import Depends, FastAPI
from sqlalchemy import Column, Integer, create_engine
from sqlalchemy.orm import Session, declarative_base, sessionmaker # type: ignore
Base = declarative_base()
class DbExample(Base): # type: ignore
__tablename__ = "app_examples"
example_id = Column(Integer, primary_key=True)
def create_db(url: str):
engine = create_engine(
url,
connect_args={"check_same_thread": False},
native_datetime=True,
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base.metadata.create_all(bind=engine)
return SessionLocal
SessionLocal = create_db("sqlite:///./real.db")
app = FastAPI()
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.get("/")
def summary(*, db: Session = Depends(get_db)):
res = db.execute("SELECT COUNT(*) FROM app_examples").scalars()
return {"result": next(res)}
# ----------------------------------------------------------------
# test_app.py
from __future__ import annotations
from fastapi.testclient import TestClient
from app import app, create_db, get_db
TEST_DB_URL = "sqlite://"
def test_root_with_context_manager() -> None:
from contextlib import contextmanager
@contextmanager
def _session():
TestingSessionLocal = create_db(TEST_DB_URL)
saved_get_db = get_db in app.dependency_overrides
old_get_db = app.dependency_overrides.get(get_db)
def override_get_db():
try:
db = TestingSessionLocal()
yield db
finally:
db.close()
app.dependency_overrides[get_db] = override_get_db
try:
yield
finally:
if saved_get_db:
app.dependency_overrides[get_db] = old_get_db
with _session():
client = TestClient(app)
client.get("/")
def test_root_with_patch() -> None:
from unittest.mock import patch
TestingSessionLocal = create_db(TEST_DB_URL)
with patch("app.SessionLocal", TestingSessionLocal):
client = TestClient(app)
client.get("/")
def test_root_by_hand() -> None:
# Trying to follow <https://fastapi.tiangolo.com/advanced/testing-database/>
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from app import Base
engine = create_engine(
TEST_DB_URL,
connect_args={"check_same_thread": False},
native_datetime=True,
)
TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base.metadata.create_all(bind=engine)
def override_get_db():
try:
db = TestingSessionLocal()
yield db
finally:
db.close()
app.dependency_overrides[get_db] = override_get_db
client = TestClient(app)
client.get("/")
Description
The above is modeled after these instructions, but those do not appear to work for SQLite’s in-memory databases. Running the following tests results in three errors similar to:
E sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: app_examples
E [SQL: SELECT COUNT(*) FROM app_examples]
E (Background on this error at: https://sqlalche.me/e/14/e3q8)
Changing TEST_DB_URL
to, e.g., sqlite:///./test.db
allows those tests to pass.
Operating System
Linux, macOS
Operating System Details
No response
FastAPI Version
0.68.1
Python Version
Python 3.9.6
Additional Context
No response
Issue Analytics
- State:
- Created 2 years ago
- Comments:7
Top Results From Across the Web
Testing EF Core in Memory using SQLite - Meziantou's blog
A good practice is to test your software. EF Core provides an In-Memory provider to easily test your code without an actual database....
Read more >EntityFrameworkCore SQLite in-memory db tables are not ...
Ensure that the database for the context exists. If it exists, no action is taken. If it does not exist then the database...
Read more >Avoid In-Memory Databases for Tests - Jimmy Bogard
The problem we hit is we can't trust the results - you hit cases where the test doesn't work. What we've hit are...
Read more >How SQLite Is Tested
There are numerous test cases that verify that SQLite is able to deal with malformed database files. These tests first build a well-formed...
Read more >Using in-memory databases for unit testing EF Core applications
Its because SQLite is a true relational database while EF Core's InMemory database provider isn't a real relational database. This means that EF ......
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
I got this to work following #1223 with:
Using this solution works for me: