Quantcast
Viewing all articles
Browse latest Browse all 14155

How to test Async SQL Databases with Encode/Databases(Package) in FastAPI

Question:

- How to run tests in isolation that don't create entries in database.- Also, How we can use the isolated user that is created during the test for other endpoint testing

Some minimal code:

from contextlib import asynccontextmanagerimport databasesimport sqlalchemyfrom fastapi import FastAPI, HTTPExceptionfrom pydantic import BaseModel, EmailStrDATABASE_URL = "postgresql://user:password@postgresserver/db"database = databases.Database(DATABASE_URL)metadata = sqlalchemy.MetaData()users = sqlalchemy.Table("users",    metadata,    sqlalchemy.Column("id", sqlalchemy.Integer, primary_key=True, index=True),    sqlalchemy.Column("first_name", sqlalchemy.String, nullable=True),    sqlalchemy.Column("last_name", sqlalchemy.String, nullable=True),    sqlalchemy.Column("email", sqlalchemy.String, index=True,                      nullable=False, unique=True),    sqlalchemy.Column("password", sqlalchemy.String,                      index=True, nullable=False),)engine = sqlalchemy.create_engine(    DATABASE_URL)metadata.create_all(engine)class UserBase(BaseModel):    first_name: str | None    last_name: str | None    email: EmailStrclass UserCreate(UserBase):    password: strapp = FastAPI()@asynccontextmanagerasync def lifespan(app: FastAPI):    await database.connect()    yield    await database.disconnect()app = FastAPI(lifespan=lifespan)class UserRepository:    async def create(self, obj_in: UserCreate):        query = users.insert().values(            first_name=obj_in.first_name,            last_name=obj_in.last_name,            email=obj_in.email,            password=obj_in.password,        )        await database.execute(query=query)        return obj_in    async def get_by_email(self, email: str):        query = users.select().where(email == users.c.email)        return await database.fetch_one(query=query)user_repository = UserRepository()@app.post("/", response_model=UserBase)async def create_user(    payload: UserCreate,):    if await user_repository.get_by_email(payload.email):        raise HTTPException(            status_code=400,            detail="The user with this username already exists in the database.",        )    return await user_repository.create(payload)##### Testing import pytestfrom fastapi.testclient import TestClient@pytest.fixture()def client():    with TestClient(app) as c:        yield c@pytest.fixture(scope="session")async def db():    database = databases.Database(DATABASE_URL, force_rollback=True)    await database.connect()    yield database    await database.disconnect()async def test_create_user_endpoint(client: TestClient):    user_data = UserCreate(        first_name="John",        last_name="Doe",        email="JohnDoe@example.in",        password="pass123",    )    response = client.post("/", json=user_data.dict())    assert response.status_code == 200    created_user = response.json()    assert created_user["first_name"] == "John"    assert created_user["last_name"] == "Doe"

The issue at involves unexpected behavior when running a FastAPI test multiple times using Pytest. The intention is to ensure test isolation by utilizing the force_rollback=True option in the test database fixture. However, despite using this option, the test fails on subsequent runs, indicating that the user already exists in the database.


Viewing all articles
Browse latest Browse all 14155

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>