from __future__ import annotations from collections.abc import Callable, Iterator import pytest from fastapi import FastAPI from fastapi.testclient import TestClient from sqlalchemy import create_engine from sqlalchemy.engine import Engine from sqlalchemy.orm import sessionmaker from sqlalchemy.pool import StaticPool from config.database import Base from dependencies import get_unit_of_work from routes.dashboard import router as dashboard_router from routes.projects import router as projects_router from routes.scenarios import router as scenarios_router from services.unit_of_work import UnitOfWork @pytest.fixture() def engine() -> Iterator[Engine]: engine = create_engine( "sqlite+pysqlite:///:memory:", future=True, connect_args={"check_same_thread": False}, poolclass=StaticPool, ) Base.metadata.create_all(bind=engine) try: yield engine finally: Base.metadata.drop_all(bind=engine) engine.dispose() @pytest.fixture() def session_factory(engine: Engine) -> Iterator[sessionmaker]: testing_session = sessionmaker(bind=engine, expire_on_commit=False, future=True) yield testing_session @pytest.fixture() def app(session_factory: sessionmaker) -> FastAPI: application = FastAPI() application.include_router(dashboard_router) application.include_router(projects_router) application.include_router(scenarios_router) def _override_uow() -> Iterator[UnitOfWork]: with UnitOfWork(session_factory=session_factory) as uow: yield uow application.dependency_overrides[get_unit_of_work] = _override_uow return application @pytest.fixture() def client(app: FastAPI) -> Iterator[TestClient]: test_client = TestClient(app) try: yield test_client finally: test_client.close() @pytest.fixture() def unit_of_work_factory(session_factory: sessionmaker) -> Callable[[], UnitOfWork]: def _factory() -> UnitOfWork: return UnitOfWork(session_factory=session_factory) return _factory