tortoise / tortoise-orm

Familiar asyncio ORM for python, built with relations in mind
https://tortoise.github.io
Apache License 2.0
4.58k stars 378 forks source link

Connection closes if save method was triggered in pytest. #1558

Open kayprogrammer opened 7 months ago

kayprogrammer commented 7 months ago

Describe the bug Whenever I'm testing my API built with Litestar and Tortoise ORM, the connection closes if there's an interac

To Reproduce

    async def test_verify_email(client, test_user: User):
        otp = "111111"

        # Verify that the email verification fails with an invalid otp
        response = await client.post(
            f"{BASE_URL_PATH}/verify-email", json={"email": test_user.email, "otp": otp}
        )
        assert response.status_code == 404
        assert response.json() == {
            "status": "failure",
            "code": ErrorCode.INCORRECT_OTP,
            "message": "Incorrect Otp",
        }
        # Verify that the email verification succeeds with a valid otp
        otp = await Otp.create(user_id=test_user.id)

        response = await client.post(
            f"{BASE_URL_PATH}/verify-email",
            json={"email": test_user.email, "otp": otp.code},
        )
        assert response.status_code == 200
        assert response.json() == {
            "status": "success",
            "message": "Account verification successful",
        }

The test_user is a fixture that creates a test user. But once it does the test fails with connection closed error at this line:

response = await client.post(
    f"{BASE_URL_PATH}/verify-email", json={"email": test_user.email, "otp": otp}
)

If the client and test_user parameter are interchanged like this: test_user: User, client, test still fails with the same error but in this line: Otp.create(user_id=test_user.id). So whichever goes first, it closes the connection unexpectedly.

Here's my db config:

MODELS = [
    "app.db.models.base",
    "app.db.models.general",
    "app.db.models.accounts",
]

TORTOISE_ORM = {
    "connections": {"default": settings.TORTOISE_DATABASE_URL},
    "apps": {
        "models": {
            "models": MODELS
            + [
                "aerich.models",
            ],
            "default_connection": "default",
        },
    },
}

@asynccontextmanager
async def lifespan(app: Litestar):
    await Tortoise.init(config=TORTOISE_ORM)
    yield
    await connections.close_all()