Problem with tests in FastAPI and Tortoise ORM

875 Views Asked by At

I have a problem with running tests. I use FastAPI with Tortoise ORM, and normally I use sqlite file to store my data in a file (for now, I'll use probably postges on production) and everything is OK. The problem shows up when I'm trying to run tests. I want to override database URL to be in-memory database, but it doesn't work and uses this "production" database instead. When I run test after deleting the db file, they pass, but next time it doesn't, because user I create during test already exists. How can I force my configuration to override db url?

main.py


from fastapi import FastAPI, Depends
from fastapi.security import OAuth2PasswordRequestForm

from tortoise.contrib.fastapi import register_tortoise

import users.router
from common.authentication import authenticate_user, create_access_token

app = FastAPI()

app.include_router(users.router.router)


@app.post("/obtain-token")
async def obtain_token(form_data: OAuth2PasswordRequestForm = Depends()):
    user = await authenticate_user(form_data.username, form_data.password)
    access_token_expires = timedelta(minutes=5)
    access_token = await create_access_token(
        user, expires_delta=access_token_expires
    )
    return {"access_token": access_token, "token_type": "bearer"}


register_tortoise(
    app,
    db_url="sqlite://db.sqlite3",
    modules={"models": ["users.models"]},
    generate_schemas=True,
    add_exception_handlers=True
)

conftest.py

import os
from typing import Generator

import pytest
from fastapi.testclient import TestClient

from tortoise.contrib.test import finalizer, initializer

from ..main import app

DB_URL = "sqlite://:memory:"


@pytest.fixture(scope="session")
def event_loop():
    return asyncio.get_event_loop()


@pytest.fixture(scope="session")
def client() -> Generator:
    initializer(
        db_url=DB_URL,
        modules=["users.models"],
    )

    with TestClient(app) as c:
        yield c

    finalizer()

test_users.py


from starlette.testclient import TestClient


def test_create_user(client: TestClient, event_loop: asyncio.AbstractEventLoop):
    user_data = {
        "username": "testUser",
        "password": "testPassword",
        "name": "testName",
        "last_name": "testLastName",
        "role": 1
    }

    response = client.post("/user/", json=user_data)
    assert response.status_code == 200

I tried setting URL in environment variables and change it in pytest fixture, but it didn't help.

I don't want to remove db file after testing, because it could remove my data I use to develop app and my manual testing.

1

There are 1 best solutions below

0
On

Stuck with same problem. The solution for me was to download a later version (0.17.0 is stable)