""" pytest fixtures for VMIS backend testing. Uses SQLite in-memory DB (no external DB required for unit tests). """ import pytest from unittest.mock import patch from fastapi.testclient import TestClient from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from sqlalchemy.pool import StaticPool from app.core.database import Base, get_db # ⚠️ Import all models BEFORE create_all so SQLAlchemy registers the tables import app.models # noqa: F401 from app.main import app TEST_DATABASE_URL = "sqlite:///:memory:" # StaticPool ensures all connections share the same in-memory SQLite database engine = create_engine( TEST_DATABASE_URL, connect_args={"check_same_thread": False}, poolclass=StaticPool, ) TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) @pytest.fixture(scope="function") def db(): """Create fresh DB tables for each test.""" Base.metadata.create_all(bind=engine) session = TestingSessionLocal() try: yield session finally: session.close() Base.metadata.drop_all(bind=engine) @pytest.fixture(scope="function") def client(db): """TestClient with DB override. Patches lifespan to skip real DB/scheduler.""" def override_get_db(): try: yield db finally: pass app.dependency_overrides[get_db] = override_get_db # Patch lifespan startup/shutdown to avoid connecting to real DB or starting scheduler with patch("app.main.seed_initial_data"), \ patch("app.main.start_watchdog"), \ patch("app.main.stop_watchdog"): with TestClient(app, raise_server_exceptions=True) as c: yield c app.dependency_overrides.clear() @pytest.fixture def sample_tenant(client): """Create and return a sample tenant.""" payload = { "code": "TEST01", "prefix": "TC", "name": "測試租戶一", "domain": "test01.lab.taipei", "status": "trial", } resp = client.post("/api/v1/tenants", json=payload) assert resp.status_code == 201 return resp.json() @pytest.fixture def sample_account(client, sample_tenant): """Create and return a sample account.""" payload = { "tenant_id": sample_tenant["id"], "sso_account": "user01", "notification_email": "user01@external.com", "quota_limit": 20, } resp = client.post("/api/v1/accounts", json=payload) assert resp.status_code == 201 return resp.json()