Spaces:
Sleeping
Sleeping
firepenguindisopanda
Add comprehensive tests for cache management, composite indexes, enum fields, and Pinecone integration
c62301e | """Tests for cache management API endpoints.""" | |
| from unittest.mock import AsyncMock, MagicMock, patch | |
| import pytest | |
| from fastapi.testclient import TestClient | |
| def mock_user(): | |
| """Create a mock user for auth dependency override.""" | |
| from app.core import models | |
| user = MagicMock(spec=models.User) | |
| user.id = 1 | |
| return user | |
| def client(mock_user): | |
| """Test client with auth dependency overridden.""" | |
| from app.main import app | |
| from app.routers.auth import get_current_user | |
| # Override auth to return mock user | |
| def _override_user(): | |
| return mock_user | |
| app.dependency_overrides[get_current_user] = _override_user | |
| yield TestClient(app) | |
| app.dependency_overrides.pop(get_current_user, None) | |
| def mock_cache_health_ok(): | |
| """Patch get_cache().get_cache_health to return healthy status.""" | |
| with patch("app.routers.cache.get_cache") as mock_get_cache: | |
| mock_cache = MagicMock() | |
| # Methods called with await need to be AsyncMock | |
| mock_cache.get_cache_health = AsyncMock() | |
| mock_cache.get_cache_health.return_value = { | |
| "status": "ok", | |
| "keys_tracked": 5, | |
| "ttl_seconds": 300, | |
| } | |
| mock_cache.invalidate_user_cache = AsyncMock() | |
| mock_cache.invalidate_user_cache.return_value = 3 | |
| mock_get_cache.return_value = mock_cache | |
| yield mock_cache | |
| def mock_cache_degraded(): | |
| """Patch get_cache().get_cache_health to return degraded status.""" | |
| with patch("app.routers.cache.get_cache") as mock_get_cache: | |
| mock_cache = MagicMock() | |
| mock_cache.get_cache_health = AsyncMock() | |
| mock_cache.get_cache_health.return_value = { | |
| "status": "degraded", | |
| "keys_tracked": 0, | |
| "ttl_seconds": 300, | |
| } | |
| mock_cache.invalidate_user_cache = AsyncMock() | |
| mock_cache.invalidate_user_cache.return_value = 0 | |
| mock_get_cache.return_value = mock_cache | |
| yield mock_cache | |
| class TestCacheInvalidateEndpoint: | |
| """Tests for POST /api/v1/cache/invalidate.""" | |
| def test_invalidate_returns_ok(self, client, mock_cache_health_ok): | |
| """Invalidate should return 200 with keys_cleared count.""" | |
| response = client.post("/api/v1/cache/invalidate") | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert data["status"] == "ok" | |
| assert data["keys_cleared"] == 3 | |
| def test_invalidate_degraded(self, client, mock_cache_degraded): | |
| """Invalidate should return degraded status when Redis unavailable.""" | |
| response = client.post("/api/v1/cache/invalidate") | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert data["status"] == "degraded" | |
| assert data["keys_cleared"] == 0 | |
| def test_invalidate_requires_auth(self): | |
| """Invalidate should return 401 without auth token.""" | |
| from app.main import app | |
| client = TestClient(app) | |
| response = client.post( | |
| "/api/v1/cache/invalidate", | |
| headers={"Authorization": "Bearer invalid-token"}, | |
| ) | |
| # Should be 401 or 403 when unauthenticated | |
| assert response.status_code in (401, 403) | |
| class TestCacheHealthEndpoint: | |
| """Tests for GET /api/v1/cache/health.""" | |
| def test_health_ok(self, client, mock_cache_health_ok): | |
| """Health endpoint should return cache status.""" | |
| response = client.get("/api/v1/cache/health") | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert data["status"] == "ok" | |
| assert data["keys_tracked"] == 5 | |
| assert data["ttl_seconds"] == 300 | |
| def test_health_degraded(self, client, mock_cache_degraded): | |
| """Health endpoint should return degraded when Redis unavailable.""" | |
| response = client.get("/api/v1/cache/health") | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert data["status"] == "degraded" | |
| assert data["keys_tracked"] == 0 | |
| def test_health_requires_auth(self): | |
| """Health endpoint should return 401 without auth token.""" | |
| from app.main import app | |
| client = TestClient(app) | |
| response = client.get( | |
| "/api/v1/cache/health", | |
| headers={"Authorization": "Bearer invalid-token"}, | |
| ) | |
| assert response.status_code in (401, 403) | |