diff --git a/backend/tests/conftest.py b/backend/tests/conftest.py index 2003eb5..491cd3c 100644 --- a/backend/tests/conftest.py +++ b/backend/tests/conftest.py @@ -2,6 +2,7 @@ from pathlib import Path import pytest +import pytest_asyncio from cryptography.fernet import Fernet os.environ.setdefault("DATABASE_URL", "sqlite+aiosqlite:///:memory:") @@ -12,6 +13,24 @@ os.environ.setdefault("AUTH_COOKIE_ENABLED", "false") +@pytest_asyncio.fixture(scope="session", autouse=True) +async def _dispose_app_engine(): + """Dispose the global app engine before the session event loop closes. + + Tests that exercise the real ``app.models.base.async_session_factory`` open + aiosqlite connections on the module-level ``engine`` that nothing else tears + down. With a session-scoped loop those connections' worker threads outlive + individual tests; when the loop finally closes, the daemon thread calls + ``call_soon_threadsafe`` on it and pytest surfaces a + ``PytestUnhandledThreadExceptionWarning: RuntimeError: Event loop is closed``. + Disposing here closes those connections while the loop is still running. + """ + yield + from app.models import base as base_mod + + await base_mod.engine.dispose() + + def pytest_collection_modifyitems(items: list[pytest.Item]) -> None: """Auto-apply 'unit' or 'integration' markers based on test file location.""" for item in items: