import pytest
from unittest.mock import MagicMock, AsyncMock
from fastapi import FastAPI
from fastapi.testclient import TestClient
from httpx import AsyncClient, ASGITransport
from sqlalchemy.orm import Session
from app.api.dependencies import get_db, ServiceContainer
from app.core.services.rag import RAGService
from app.core.services.document import DocumentService
from app.core.services.tts import TTSService
from app.core.services.stt import STTService
from app.api.routes.api import create_api_router
# Change the scope to "function" so the fixture is re-created for each test
@pytest.fixture(scope="function")
def client():
"""
Pytest fixture to create a TestClient with a fully mocked environment
for synchronous endpoints, scoped to a single function.
"""
test_app = FastAPI()
# Create mocks for all individual services
mock_rag_service = MagicMock(spec=RAGService)
mock_document_service = MagicMock(spec=DocumentService)
mock_tts_service = MagicMock(spec=TTSService)
mock_stt_service = MagicMock(spec=STTService)
# Create a mock for the ServiceContainer and attach all the individual service mocks
mock_services = MagicMock(spec=ServiceContainer)
mock_services.rag_service = mock_rag_service
mock_services.document_service = mock_document_service
mock_services.tts_service = mock_tts_service
mock_services.stt_service = mock_stt_service
# Mock the database session
mock_db_session = MagicMock(spec=Session)
# Dependency override for the database session
def override_get_db():
yield mock_db_session
# Create the API router and include it in the test app
api_router = create_api_router(services=mock_services)
test_app.dependency_overrides[get_db] = override_get_db
test_app.include_router(api_router)
test_client = TestClient(test_app)
yield test_client, mock_services
@pytest.fixture(scope="function")
async def async_client():
"""
Pytest fixture to create an AsyncClient for testing async endpoints,
scoped to a single function.
"""
test_app = FastAPI()
# Create mocks for all individual services
mock_rag_service = MagicMock(spec=RAGService)
mock_document_service = MagicMock(spec=DocumentService)
mock_tts_service = MagicMock(spec=TTSService)
mock_stt_service = MagicMock(spec=STTService)
# Create a mock for the ServiceContainer and attach all the individual service mocks
mock_services = MagicMock(spec=ServiceContainer)
mock_services.rag_service = mock_rag_service
mock_services.document_service = mock_document_service
mock_services.tts_service = mock_tts_service
mock_services.stt_service = mock_stt_service
# Mock the database session
mock_db_session = MagicMock(spec=Session)
# Dependency override for the database session
def override_get_db():
yield mock_db_session
# Create the API router and include it in the test app
api_router = create_api_router(services=mock_services)
test_app.dependency_overrides[get_db] = override_get_db
test_app.include_router(api_router)
# Use ASGITransport for testing async code
async with AsyncClient(transport=ASGITransport(app=test_app), base_url="http://test") as client:
yield client, mock_services