tipitaka / webapp /tipitaka-api /tests /test_rag_service.py
dhammawatthumpra's picture
feat: complete turbovec search backend integration, ignore tvim file in git, and stabilize mobile UI transitions
603ead8
Raw
History Blame Contribute Delete
2.39 kB
"""
Unit tests for RAGService — embedding cache, Qdrant client.
Uses mocked dependencies to test in isolation.
"""
import pytest
from unittest.mock import MagicMock, patch
class TestEmbeddingCache:
@pytest.fixture
def rag_service(self):
from app.services.rag_service import RAGService
with patch.object(RAGService, '_load_model'), \
patch.object(RAGService, '_load_reranker'), \
patch.object(RAGService, '_init_turbovec'):
service = RAGService()
service.tv_index = MagicMock()
return service
def test_cache_initialized(self, rag_service):
assert rag_service._embed_cache is not None
assert rag_service._embed_cache_max == 256
def test_cache_stores_and_returns(self, rag_service):
"""Cache should store and return the same value for identical input."""
mock_response = MagicMock()
mock_response.json.return_value = {"embeddings": [[0.1, 0.2, 0.3]]}
mock_response.raise_for_status.return_value = None
with patch("app.services.rag_service.httpx.post", return_value=mock_response):
emb1 = rag_service._get_embedding("test query")
# Second call should use cache (no httpx call)
emb2 = rag_service._get_embedding("test query")
assert emb1 == emb2
def test_cache_max_respected(self, rag_service):
"""When cache exceeds max, oldest entries should be evicted."""
old_entry = "a" * 10
for i in range(rag_service._embed_cache_max + 5):
rag_service._embed_cache[f"key_{i}"] = [0.1] * 1024
if len(rag_service._embed_cache) > rag_service._embed_cache_max:
rag_service._embed_cache.popitem(last=False)
assert len(rag_service._embed_cache) <= rag_service._embed_cache_max
class TestRAGServiceInit:
def test_init_graceful_on_turbovec_failure(self):
"""RAGService constructor should not crash when turbovec is unavailable."""
from app.services.rag_service import RAGService
with patch.object(RAGService, '_load_model'), \
patch.object(RAGService, '_load_reranker'), \
patch.object(RAGService, '_init_turbovec') as mock_init:
service = RAGService()
mock_init.assert_called_once()
assert service.tv_index is None # _init_turbovec didn't set it