tortoise / tortoise/tortoise-orm

db_url parameter is initializer is ignored and db passed in register_tortoise is used instead

Open
#704 6 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
5.6k
Forks
516
Avg merge
2d 21h
Merged PRs (30d)
9

Description

I'm trying to create a test with pytest for my FastAPI + Tortoise ORM app.
To start, I am using the example provided in the documentation.

main.py:

from typing import List
from pydantic import UUID4
from fastapi import Depends, FastAPI, HTTPException, Request
from . import crud, models, schemas, auth
from tortoise.contrib.fastapi import HTTPNotFoundError, register_tortoise
from fastapi_users import FastAPIUsers
from .config import JWT_SECRET, ADMIN_PW
from .workers import selenium, jobs

app = FastAPI()

...

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

My test.py:

# mypy: no-disallow-untyped-decorators
# pylint: disable=E0611,E0401
import asyncio
from typing import Generator

import pytest
from fastapi.testclient import TestClient
from .. import models
from ..main import app

from tortoise.contrib.test import finalizer, initializer


@pytest.fixture(scope="module")
def client() -> Generator:
    initializer(modules=["app.models"], db_url="sqlite://./test_db.sqlite3")
    with TestClient(app) as c:
        yield c
    finalizer()


@pytest.fixture(scope="module")
def event_loop(client: TestClient) -> Generator:
    yield client.task.get_loop()


def test_create_user(
    client: TestClient, event_loop: asyncio.AbstractEventLoop
):  # nosec
    response = client.post(
        "/auth/register",
        json={
            "email": "test@test.com",
            "password": "string",
            "is_active": True,
            "is_superuser": False,
            "is_verified": False,
        },
    )
    assert response.status_code == 201, response.text
    data = response.json()
    assert data["email"] == "test@test.com"
    assert "id" in data
    user_id = data["id"]

    async def get_user_by_db():
        user = await models.UserModel.get(id=user_id)
        return user

    user_obj = event_loop.run_until_complete(get_user_by_db())
    assert user_obj.id == user_id

Yet, the data is written to db.sqlite3 in the root folder and even not cleaned at the end of the test (the data remains in the database).
I have also tried using sqlite://:memory: but to no avail. It always defaults to db.sqlite3.

Is this a bug or am I doing something wrong?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Inspect the register_tortoise call in main.py alongside the initializer and finalizer fixtures in test.py. Reproduce the behavior with the shown pytest setup, then trace which database configuration the application uses during the test. Done means the test writes to test_db.sqlite3 or the in-memory database rather than db.sqlite3, and cleanup removes the test data.

Written by the indexing model from the issue text.

Assessment

Tech stack
fastapi, python, sqlite
Domain
database, testing
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.