Agentic-RagBot / tests /test_main.py
MediGuard AI
feat: Initial release of MediGuard AI v2.0
c4f5f25
"""Tests for main FastAPI application."""
import pytest
from fastapi.testclient import TestClient
from fastapi.middleware.cors import CORSMiddleware
from unittest.mock import Mock, patch
from src.main import create_app, lifespan
class TestMainApp:
"""Test main FastAPI application."""
def test_create_app(self):
"""Test app creation."""
app = create_app()
assert app is not None
assert app.title == "MediGuard AI"
assert app.version == "2.0.0"
@pytest.mark.asyncio
@patch('src.main.logger')
@patch('src.main.get_settings')
async def test_lifespan_startup(self, mock_settings, mock_logger):
"""Test lifespan context manager startup."""
from unittest.mock import MagicMock, patch
# Mock all service imports to avoid heavy initialization
with patch('src.services.opensearch.client.make_opensearch_client'), \
patch('src.services.embeddings.service.make_embedding_service'), \
patch('src.services.cache.redis_cache.make_redis_cache'), \
patch('src.services.ollama.client.make_ollama_client'), \
patch('src.services.langfuse.tracer.make_langfuse_tracer'), \
patch('src.services.agents.agentic_rag.AgenticRAGService'), \
patch('src.workflow.create_guild'), \
patch('src.services.extraction.service.make_extraction_service'):
app = MagicMock()
state = MagicMock()
app.state = state
async with lifespan(app):
# Check startup actions
assert hasattr(app.state, 'start_time')
assert hasattr(app.state, 'version')
assert app.state.version == "2.0.0"
mock_logger.info.assert_called()
@pytest.mark.asyncio
@patch('src.main.logger')
@patch('src.main.get_settings')
async def test_lifespan_shutdown(self, mock_settings, mock_logger):
"""Test lifespan context manager shutdown."""
from unittest.mock import MagicMock, patch
# Mock all service imports to avoid heavy initialization
with patch('src.services.opensearch.client.make_opensearch_client'), \
patch('src.services.embeddings.service.make_embedding_service'), \
patch('src.services.cache.redis_cache.make_redis_cache'), \
patch('src.services.ollama.client.make_ollama_client'), \
patch('src.services.langfuse.tracer.make_langfuse_tracer'), \
patch('src.services.agents.agentic_rag.AgenticRAGService'), \
patch('src.workflow.create_guild'), \
patch('src.services.extraction.service.make_extraction_service'):
app = MagicMock()
state = MagicMock()
app.state = state
async with lifespan(app):
pass
# Check shutdown was logged
mock_logger.info.assert_any_call("Shutting down MediGuard AI …")
def test_app_includes_routers(self):
"""Test that app includes all routers."""
app = create_app()
# Check that routes are registered
routes = [route.path for route in app.routes]
expected_routes = ["/analyze", "/ask", "/search", "/health"]
for route in expected_routes:
assert any(route in r for r in routes)
def test_app_cors_middleware(self):
"""Test CORS middleware is configured."""
app = create_app()
# Find CORS middleware
cors_middleware = None
for middleware in app.user_middleware:
if middleware.cls == CORSMiddleware:
cors_middleware = middleware
break
assert cors_middleware is not None
def test_global_exception_handler(self):
"""Test global exception handler."""
app = create_app()
client = TestClient(app)
# Trigger a validation error
response = client.post("/analyze/structured", json={"invalid": "data"})
assert response.status_code == 422
assert "details" in response.json()
def test_health_endpoint(self):
"""Test health endpoint."""
app = create_app()
client = TestClient(app)
response = client.get("/health")
assert response.status_code == 200
assert "status" in response.json()
assert response.json()["status"] == "healthy"