""" Tests for RAG service module. """ import pytest from pathlib import Path from unittest.mock import patch, MagicMock from app.core.rag import ( RAGService, CORPUS_DIR, VECTOR_STORE_PATH, ) class TestRAGServiceInit: """Tests for RAGService initialization.""" @patch("app.core.rag.get_embeddings_model") def test_creates_embeddings(self, mock_embeddings): """RAGService should initialize embeddings.""" mock_embeddings.return_value = MagicMock() with patch.object(RAGService, "_initialize_vector_store"): service = RAGService() assert mock_embeddings.called assert service.embeddings is not None @patch("app.core.rag.get_embeddings_model") @patch("app.core.rag.os.getenv") def test_fallback_without_pinecone(self, mock_getenv, mock_embeddings): """Should use fallback when Pinecone not configured.""" mock_embeddings.return_value = MagicMock() mock_getenv.return_value = None # No Pinecone config with patch.object(RAGService, "_init_fallback") as mock_fallback: service = RAGService() # Should attempt fallback mock_fallback.assert_called_once() class TestRAGServicePaths: """Tests for RAG service path constants.""" def test_corpus_dir_defined(self): """CORPUS_DIR should be defined.""" assert CORPUS_DIR is not None assert isinstance(CORPUS_DIR, Path) def test_vector_store_path_defined(self): """VECTOR_STORE_PATH should be defined.""" assert VECTOR_STORE_PATH is not None assert isinstance(VECTOR_STORE_PATH, Path) class TestRAGServiceRetrieve: """Tests for RAGService retrieve functionality.""" @patch("app.core.rag.get_embeddings_model") def test_retrieve_no_store(self, mock_embeddings): """Retrieve should handle missing vector store gracefully.""" mock_embeddings.return_value = MagicMock() with patch.object(RAGService, "_initialize_vector_store"): service = RAGService() service.vector_store = None result = service.retrieve("test query") assert result == [] @patch("app.core.rag.get_embeddings_model") def test_format_docs_empty(self, mock_embeddings): """format_docs should handle empty list.""" mock_embeddings.return_value = MagicMock() with patch.object(RAGService, "_initialize_vector_store"): service = RAGService() result = service.format_docs([]) assert "No relevant context" in result class TestRAGServiceFormatDocs: """Tests for document formatting.""" @patch("app.core.rag.get_embeddings_model") def test_format_single_doc(self, mock_embeddings): """Should format single document correctly.""" from langchain_core.documents import Document mock_embeddings.return_value = MagicMock() with patch.object(RAGService, "_initialize_vector_store"): service = RAGService() doc = Document( page_content="Test content", metadata={"source": "test.md"}, ) result = service.format_docs([doc]) assert "Test content" in result assert "test.md" in result @patch("app.core.rag.get_embeddings_model") def test_format_multiple_docs(self, mock_embeddings): """Should format multiple documents.""" from langchain_core.documents import Document mock_embeddings.return_value = MagicMock() with patch.object(RAGService, "_initialize_vector_store"): service = RAGService() docs = [ Document(page_content="Content 1", metadata={"source": "doc1.md"}), Document(page_content="Content 2", metadata={"source": "doc2.md"}), ] result = service.format_docs(docs) assert "Content 1" in result assert "Content 2" in result assert "doc1.md" in result assert "doc2.md" in result class TestRAGServiceRetriever: """Tests for retriever interface.""" @patch("app.core.rag.get_embeddings_model") def test_get_retriever_raises_without_store(self, mock_embeddings): """get_retriever should raise if no vector store.""" mock_embeddings.return_value = MagicMock() with patch.object(RAGService, "_initialize_vector_store"): service = RAGService() service.vector_store = None with pytest.raises(RuntimeError, match="not initialized"): service.get_retriever() @patch("app.core.rag.get_embeddings_model") def test_get_retriever_with_store(self, mock_embeddings): """get_retriever should return retriever when store exists.""" mock_embeddings.return_value = MagicMock() mock_store = MagicMock() mock_retriever = MagicMock() mock_store.as_retriever.return_value = mock_retriever with patch.object(RAGService, "_initialize_vector_store"): service = RAGService() service.vector_store = mock_store retriever = service.get_retriever(k=5) mock_store.as_retriever.assert_called_once() assert retriever == mock_retriever