import os from unittest import mock import pytest from fastapi.testclient import TestClient from sqlalchemy import StaticPool, create_engine, event from sqlalchemy.orm import sessionmaker from allmende_payment_system.api.dependencies import get_session from allmende_payment_system.app import app from allmende_payment_system.models import Base engine = create_engine( "sqlite:///:memory:", connect_args={"check_same_thread": False}, poolclass=StaticPool, ) # Create a single connection and an outer transaction which we can rollback # at the end of the test run. Individual tests will use nested transactions # (SAVEPOINTs) for isolation. This ensures the TestClient (app) and the # test fixture sessions see the same in-memory database state. connection = engine.connect() transaction = connection.begin() Base.metadata.create_all(bind=connection) # Bind sessions to the single connection so all sessions share the same DB TestSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=connection) test_session = None def get_test_session(): """Dependency override for get_session""" assert test_session is not None, "test_session is not set" yield test_session test_session.flush() app.dependency_overrides[get_session] = get_test_session @pytest.fixture(scope="session") def client(): os.environ["APS_username"] = "test" return TestClient(app) @pytest.fixture(scope="session") def unauthorized_client(): os.environ.pop("APS_username", None) return TestClient(app) @pytest.fixture(scope="function") def test_db(): """Provides a database session for direct test usage""" db = TestSessionLocal() global test_session test_session = db try: yield db finally: test_session = None db.rollback() db.close()