diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 0dabe12..98a8aa2 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -95,6 +95,16 @@ no_implicit_optional = true [tool.pytest.ini_options] asyncio_mode = "auto" +# pytest-asyncio 1.x ignores the old session-scoped ``event_loop`` fixture and +# defaults fixtures + tests to function-scoped loops. The integration suite +# shares a session-scoped engine whose in-memory SQLite (aiosqlite) connection +# is bound to the loop it was created on; with function-scoped test loops that +# connection is used from a different/closed loop → "Event loop is closed" / +# "no such table: users" cascades (Linux CI; macOS happened to tolerate it). +# Pin both fixtures and tests to one session loop so the shared engine stays +# valid for every test — restoring the pre-1.x behaviour. +asyncio_default_fixture_loop_scope = "session" +asyncio_default_test_loop_scope = "session" testpaths = ["tests"] markers = [ "unit: unit tests (deselect with '-m \"not unit\"')", diff --git a/backend/tests/integration/conftest.py b/backend/tests/integration/conftest.py index c9c3c03..a871bce 100644 --- a/backend/tests/integration/conftest.py +++ b/backend/tests/integration/conftest.py @@ -4,11 +4,9 @@ dependency so every endpoint hits an actual DB instead of mocks. """ -import asyncio import uuid from collections.abc import AsyncGenerator -import pytest import pytest_asyncio from httpx import ASGITransport, AsyncClient from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine @@ -51,13 +49,6 @@ from app.models.base import Base -@pytest.fixture(scope="session") -def event_loop(): - loop = asyncio.new_event_loop() - yield loop - loop.close() - - @pytest_asyncio.fixture(scope="session") async def engine(): from app.models.base import enable_sqlite_fk