"""Shared test fixtures (SQLite memory DB, AsyncSessionLocal monkeypatch).""" from __future__ import annotations import asyncio from collections.abc import AsyncGenerator, Generator import pytest import pytest_asyncio from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine import app.db.models # noqa: F401 # register ORM tables on Base.metadata from app.db.base import Base @pytest_asyncio.fixture async def sqlite_session_factory() -> AsyncGenerator[async_sessionmaker[AsyncSession], None]: """In-memory SQLite + create_all; yields async_sessionmaker.""" engine = create_async_engine("sqlite+aiosqlite:///:memory:") async with engine.begin() as conn: await conn.run_sync(Base.metadata.create_all) factory = async_sessionmaker( engine, class_=AsyncSession, expire_on_commit=False, autoflush=False, autobegin=False, ) yield factory await engine.dispose() @pytest.fixture def patched_async_session_local( monkeypatch: pytest.MonkeyPatch, ) -> Generator[async_sessionmaker[AsyncSession], None, None]: """ Replace AsyncSessionLocal in modules that open DB sessions, for sync tests (e.g. TestClient) that use asyncio.run internally. """ engine = create_async_engine("sqlite+aiosqlite:///:memory:") async def _init() -> None: async with engine.begin() as conn: await conn.run_sync(Base.metadata.create_all) asyncio.run(_init()) factory = async_sessionmaker( engine, class_=AsyncSession, expire_on_commit=False, autoflush=False, autobegin=False, ) monkeypatch.setattr( "app.services.video.session_manager.AsyncSessionLocal", factory, ) monkeypatch.setattr( "app.services.surgery_pipeline.AsyncSessionLocal", factory, ) monkeypatch.setattr( "app.services.voice_resolution.AsyncSessionLocal", factory, ) yield factory async def _dispose() -> None: await engine.dispose() asyncio.run(_dispose())