Spaces:
Sleeping
Sleeping
| # tests/routes/test_patient_routes.py | |
| from datetime import datetime, timezone | |
| from unittest.mock import MagicMock | |
| import pytest | |
| from fastapi import FastAPI, status | |
| from fastapi.testclient import TestClient | |
| from src.api.routes.patient import router as patient_router | |
| from src.core.state import get_state | |
| from src.models.patient import Patient | |
| from src.models.session import Session | |
| # --- Test Setup: Mocking and Dependency Injection --- | |
| # Mock the service layer that the API routes depend on. | |
| mock_memory_manager = MagicMock() | |
| # This mock AppState and override function will replace the real dependencies. | |
| class MockAppState: | |
| def __init__(self): | |
| self.memory_manager = mock_memory_manager | |
| def override_get_state() -> MockAppState: | |
| return MockAppState() | |
| # Create a FastAPI app instance for testing and apply the dependency override. | |
| app = FastAPI() | |
| app.include_router(patient_router) | |
| app.dependency_overrides[get_state] = override_get_state | |
| # --- Fixtures --- | |
| def client(): | |
| """Provides a TestClient for making requests to the app.""" | |
| with TestClient(app) as c: | |
| yield c | |
| def reset_mocks(): | |
| """Resets mocks before each test to ensure test isolation.""" | |
| mock_memory_manager.reset_mock() | |
| # --- Test Data --- | |
| fake_patient_dict = { | |
| "_id": "patient123", | |
| "name": "Jane Doe", | |
| "age": 42, | |
| "sex": "Female", | |
| "ethnicity": "Caucasian", | |
| "created_at": datetime.now(timezone.utc).isoformat(), | |
| "updated_at": datetime.now(timezone.utc).isoformat(), | |
| } | |
| fake_patient = Patient.model_validate(fake_patient_dict) | |
| fake_session_dict = { | |
| "_id": "session456", | |
| "account_id": "doctor789", | |
| "patient_id": "patient123", | |
| "title": "Checkup", | |
| "created_at": datetime.now(timezone.utc).isoformat(), | |
| "updated_at": datetime.now(timezone.utc).isoformat(), | |
| "messages": [], | |
| } | |
| fake_session = Session.model_validate(fake_session_dict) | |
| # --- Tests for GET /patient --- | |
| def test_search_patients_success(client: TestClient): | |
| """Tests successfully searching for patients with a query.""" | |
| mock_memory_manager.search_patients.return_value = [fake_patient] | |
| response = client.get("/patient?q=Jane&limit=5") | |
| assert response.status_code == status.HTTP_200_OK | |
| assert len(response.json()) == 1 | |
| assert response.json()[0]["name"] == "Jane Doe" | |
| mock_memory_manager.search_patients.assert_called_once_with("Jane", limit=5) | |
| def test_search_patients_requires_query(client: TestClient): | |
| """Tests that a 400 error is returned if the search query 'q' is missing.""" | |
| response = client.get("/patient") | |
| assert response.status_code == status.HTTP_400_BAD_REQUEST | |
| assert response.json()["detail"] == "A search query 'q' is required." | |
| # --- Tests for POST /patient --- | |
| def test_create_patient_success(client: TestClient): | |
| """Tests successful creation of a new patient profile.""" | |
| new_patient_id = "new_patient_abc" | |
| mock_memory_manager.create_patient.return_value = new_patient_id | |
| mock_memory_manager.get_patient_by_id.return_value = fake_patient | |
| patient_data = {"name": "Jane Doe", "age": 42, "sex": "Female", "ethnicity": "Caucasian"} | |
| response = client.post("/patient", json=patient_data) | |
| assert response.status_code == status.HTTP_201_CREATED | |
| assert response.json()["name"] == "Jane Doe" | |
| mock_memory_manager.create_patient.assert_called_once() | |
| mock_memory_manager.get_patient_by_id.assert_called_once_with(new_patient_id) | |
| def test_create_patient_invalid_data(client: TestClient): | |
| """Tests failure when the memory manager cannot create a patient (e.g., bad data).""" | |
| mock_memory_manager.create_patient.return_value = None | |
| patient_data = {"name": "Invalid", "age": -5, "sex": "F", "ethnicity": "Unknown"} | |
| response = client.post("/patient", json=patient_data) | |
| assert response.status_code == status.HTTP_400_BAD_REQUEST | |
| assert response.json()["detail"] == "Patient could not be created due to invalid data." | |
| def test_create_patient_not_found_after_creation(client: TestClient): | |
| """Tests the edge case where the patient can't be retrieved after creation.""" | |
| new_patient_id = "new_patient_abc" | |
| mock_memory_manager.create_patient.return_value = new_patient_id | |
| mock_memory_manager.get_patient_by_id.return_value = None | |
| patient_data = {"name": "Jane Doe", "age": 42, "sex": "Female", "ethnicity": "Caucasian"} | |
| response = client.post("/patient", json=patient_data) | |
| assert response.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR | |
| assert response.json()["detail"] == "Could not find newly created patient." | |
| # --- Tests for GET /patient/{patient_id} --- | |
| def test_get_patient_by_id_success(client: TestClient): | |
| """Tests successfully retrieving a single patient by their ID.""" | |
| mock_memory_manager.get_patient_by_id.return_value = fake_patient | |
| response = client.get(f"/patient/{fake_patient.id}") | |
| assert response.status_code == status.HTTP_200_OK | |
| assert response.json()["name"] == fake_patient.name | |
| mock_memory_manager.get_patient_by_id.assert_called_once_with(str(fake_patient.id)) | |
| def test_get_patient_by_id_not_found(client: TestClient): | |
| """Tests that a 404 error is returned for a non-existent patient ID.""" | |
| mock_memory_manager.get_patient_by_id.return_value = None | |
| response = client.get("/patient/non_existent_id") | |
| assert response.status_code == status.HTTP_404_NOT_FOUND | |
| assert response.json()["detail"] == "Patient not found" | |
| # --- Tests for PATCH /patient/{patient_id} --- | |
| def test_update_patient_success(client: TestClient): | |
| """Tests a successful patient profile update.""" | |
| mock_memory_manager.update_patient_profile.return_value = 1 # 1 document modified | |
| mock_memory_manager.get_patient_by_id.return_value = fake_patient | |
| update_data = {"age": 43} | |
| response = client.patch(f"/patient/{fake_patient.id}", json=update_data) | |
| assert response.status_code == status.HTTP_200_OK | |
| assert response.json()["name"] == fake_patient.name | |
| mock_memory_manager.update_patient_profile.assert_called_once_with(str(fake_patient.id), update_data) | |
| def test_update_patient_no_fields_provided(client: TestClient): | |
| """Tests that a 400 error is returned if the update request body is empty.""" | |
| response = client.patch(f"/patient/{fake_patient.id}", json={}) | |
| assert response.status_code == status.HTTP_400_BAD_REQUEST | |
| assert response.json()["detail"] == "No update fields provided." | |
| def test_update_patient_not_found(client: TestClient): | |
| """Tests updating a non-existent patient.""" | |
| mock_memory_manager.update_patient_profile.return_value = 0 | |
| # The route logic then checks if the patient exists. Simulate it not existing. | |
| mock_memory_manager.get_patient_by_id.return_value = None | |
| response = client.patch("/patient/non_existent_id", json={"age": 50}) | |
| assert response.status_code == status.HTTP_404_NOT_FOUND | |
| assert response.json()["detail"] == "Patient not found" | |
| # Check that get_patient_by_id was called as part of the 404 check | |
| mock_memory_manager.get_patient_by_id.assert_called_once_with("non_existent_id") | |
| # --- Tests for GET /patient/{patient_id}/session --- | |
| def test_list_sessions_for_patient_success(client: TestClient): | |
| """Tests successfully listing all sessions for a given patient.""" | |
| mock_memory_manager.get_patient_by_id.return_value = fake_patient | |
| mock_memory_manager.list_patient_sessions.return_value = [fake_session] | |
| response = client.get(f"/patient/{fake_patient.id}/session") | |
| assert response.status_code == status.HTTP_200_OK | |
| assert len(response.json()) == 1 | |
| assert response.json()[0]["title"] == "Checkup" | |
| # Verify it first checked that the patient exists | |
| mock_memory_manager.get_patient_by_id.assert_called_once_with(str(fake_patient.id)) | |
| mock_memory_manager.list_patient_sessions.assert_called_once_with(str(fake_patient.id)) | |
| def test_list_sessions_for_patient_not_found(client: TestClient): | |
| """Tests listing sessions for a non-existent patient.""" | |
| mock_memory_manager.get_patient_by_id.return_value = None | |
| response = client.get("/patient/non_existent_id/session") | |
| assert response.status_code == status.HTTP_404_NOT_FOUND | |
| assert response.json()["detail"] == "Patient not found" | |
| mock_memory_manager.list_patient_sessions.assert_not_called() | |