Askmydocs / tests /test_api.py
Harshita Bhatia
Fix CI: mock heavy deps at import time, add data/ dir creation
f6d8d08
import sys
import os
from unittest.mock import patch, MagicMock
# CI only installs lightweight test deps (fastapi, pytest, httpx, pydantic).
# These packages are not installed in CI because they are too large (~2GB).
# Inserting MagicMock() into sys.modules fools Python's import system into thinking they are already loaded, so the import chain succeeds without
# actually needing the real packages. The @patch decorators in each test
# then replace the specific functions with controlled mocks.
_MOCK_MODULES = [
"dotenv",
"langchain_groq",
"langchain_huggingface",
"langchain_chroma",
"langchain_community",
"langchain_community.document_loaders",
"langchain_community.retrievers",
"langchain_core",
"langchain_core.prompts",
"langchain_text_splitters",
"sentence_transformers",
"chromadb",
"rank_bm25",
"torch",
]
for _mod in _MOCK_MODULES:
sys.modules.setdefault(_mod, MagicMock())
import pytest
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from fastapi.testclient import TestClient
from api.main import app
client = TestClient(app)
def test_root():
response = client.get("/")
assert response.status_code == 200
assert response.json()["status"] == "AskMyDocs API is running"
@patch("api.main.build_vector_store_from_file")
@patch("api.main.reload_vector_store")
@patch("api.main.shutil.copyfileobj") # prevent actual file I/O
@patch("builtins.open", MagicMock())
def test_upload_pdf(mock_copy, mock_reload, mock_build):
mock_build.return_value = None
mock_reload.return_value = None
mock_copy.return_value = None
dummy_pdf = b"%PDF-1.4 fake pdf content"
response = client.post(
"/upload",
files={"file": ("test.pdf", dummy_pdf, "application/pdf")}
)
assert response.status_code == 200
assert response.json()["status"] == "indexed"
assert response.json()["filename"] == "test.pdf"
mock_build.assert_called_once()
mock_reload.assert_called_once()
@patch("api.main.ask")
def test_ask_question(mock_ask):
mock_ask.return_value = "This is a test answer [Page 1]."
response = client.post("/ask", json={"question": "What is dropout?"})
assert response.status_code == 200
assert "answer" in response.json()
assert response.json()["question"] == "What is dropout?"
@patch("api.main.ask")
def test_ask_no_document(mock_ask):
mock_ask.return_value = "Please upload a document first."
response = client.post("/ask", json={"question": "anything"})
assert response.status_code == 200
assert "answer" in response.json()
def test_ask_empty_question():
response = client.post("/ask", json={"question": ""})
assert response.status_code == 200