Skip to content

Commit

Permalink
Unit testing for schema module
Browse files Browse the repository at this point in the history
  • Loading branch information
tomsmoker committed Oct 12, 2024
1 parent 4927c12 commit a225f15
Show file tree
Hide file tree
Showing 5 changed files with 626 additions and 9 deletions.
9 changes: 4 additions & 5 deletions backend/src/app/schemas/document.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Document schemas for API requests and responses."""

from pydantic import BaseModel
from typing import Annotated
from pydantic import BaseModel, Field

from app.models.document import Document

Expand All @@ -11,18 +12,16 @@ class DocumentCreate(BaseModel):
name: str
author: str
tag: str
page_count: int
page_count: Annotated[int, Field(strict=True, gt=0)] # This ensures page_count is a non-negative integer


class DocumentResponse(Document):
"""Schema for document response, inheriting from the Document model."""

pass


class DeleteDocumentResponse(BaseModel):
"""Schema for delete document response."""

id: str
status: str
message: str
message: str
37 changes: 34 additions & 3 deletions backend/tests/app/api/v1/endpoints/test_endpoint_document.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ async def test_upload_document_endpoint(
expected_response,
):
# Given
mock_llm_service_instance = Mock()
# Mock any methods of the LLM service that are called during the test
mock_llm_service_instance.some_method = AsyncMock(return_value="mocked_response")
mock_get_llm_service.return_value = mock_llm_service_instance

mock_vector_db_factory.return_value = Mock()
mock_doc_service.return_value.upload_document = AsyncMock(
return_value=document_id
Expand Down Expand Up @@ -86,10 +91,15 @@ async def test_upload_document_endpoint(
"app.api.v1.endpoints.document.VectorDBFactory.create_vector_db_service"
)
@patch("app.api.v1.endpoints.document.DocumentService")
@patch("app.api.v1.endpoints.document.get_llm_service")
async def test_upload_document_endpoint_errors(
mock_doc_service, mock_vector_db_factory, exception, expected_status
mock_get_llm_service, mock_doc_service, mock_vector_db_factory, exception, expected_status
):
# Given
mock_llm_service_instance = Mock()
mock_llm_service_instance.some_method = AsyncMock(side_effect=exception)
mock_get_llm_service.return_value = mock_llm_service_instance

mock_vector_db_factory.return_value = Mock()
mock_doc_service.return_value.upload_document = AsyncMock(
side_effect=exception
Expand Down Expand Up @@ -135,6 +145,10 @@ async def test_upload_document_endpoint_none_document_id(
mock_get_llm_service, mock_doc_service, mock_vector_db_factory
):
# Given
mock_llm_service_instance = Mock()
mock_llm_service_instance.some_method = AsyncMock(return_value="mocked_response")
mock_get_llm_service.return_value = mock_llm_service_instance

mock_vector_db_factory.return_value = AsyncMock()
mock_doc_service.return_value.upload_document = AsyncMock(
return_value=None
Expand Down Expand Up @@ -163,6 +177,10 @@ async def test_delete_document_endpoint_none_vector_db_service(
mock_get_llm_service, mock_vector_db_factory
):
# Given
mock_llm_service_instance = Mock()
mock_llm_service_instance.some_method = AsyncMock(return_value="mocked_response")
mock_get_llm_service.return_value = mock_llm_service_instance

mock_vector_db_factory.return_value = None

# When
Expand Down Expand Up @@ -208,6 +226,10 @@ async def test_delete_document_endpoint(
expected_response,
):
# Given
mock_llm_service_instance = Mock()
mock_llm_service_instance.some_method = AsyncMock(return_value="mocked_response")
mock_get_llm_service.return_value = mock_llm_service_instance

mock_vector_db_service = AsyncMock()
mock_vector_db_service.delete_document.return_value = mock_return
mock_vector_db_factory.return_value = (
Expand Down Expand Up @@ -239,6 +261,10 @@ async def test_delete_document_endpoint_errors(
mock_get_llm_service, mock_vector_db_factory, exception, expected_status
):
# Given
mock_llm_service_instance = Mock()
mock_llm_service_instance.some_method = AsyncMock(side_effect=exception)
mock_get_llm_service.return_value = mock_llm_service_instance

mock_vector_db_service = AsyncMock()
mock_vector_db_service.delete_document.side_effect = exception
mock_vector_db_factory.return_value = mock_vector_db_service
Expand All @@ -258,10 +284,15 @@ async def test_delete_document_endpoint_errors(
)
@patch("app.api.v1.endpoints.document.DocumentService")
@patch("app.api.v1.endpoints.document.logger")
@patch("app.api.v1.endpoints.document.get_llm_service")
async def test_upload_document_endpoint_logging(
mock_logger, mock_doc_service, mock_vector_db_factory
mock_get_llm_service, mock_logger, mock_doc_service, mock_vector_db_factory
):
# Given
mock_llm_service_instance = Mock()
mock_llm_service_instance.some_method = AsyncMock(return_value="mocked_response")
mock_get_llm_service.return_value = mock_llm_service_instance

mock_vector_db_factory.return_value = Mock()
mock_doc_service.return_value.upload_document = AsyncMock(
return_value="test_doc_id"
Expand All @@ -277,4 +308,4 @@ async def test_upload_document_endpoint_logging(
# Then
mock_logger.info.assert_called_once_with(
"Endpoint received file: test.txt, content type: text/plain"
)
)
113 changes: 112 additions & 1 deletion backend/tests/app/routing_schemas/test_schema_document.py
Original file line number Diff line number Diff line change
@@ -1 +1,112 @@
"""Tests for the document routing schema"""
import pytest
from pydantic import ValidationError
from datetime import datetime
from app.schemas.document import DocumentCreate, DocumentResponse, DeleteDocumentResponse
from app.models.document import Document

class TestDocumentCreateSchema:
def test_valid_document_create(self):
# Given
document_data = {
"name": "Test Document",
"author": "John Doe",
"tag": "test",
"page_count": 10
}

# When
document = DocumentCreate(**document_data)

# Then
assert document.name == "Test Document"
assert document.author == "John Doe"
assert document.tag == "test"
assert document.page_count == 10

def test_invalid_document_create_missing_field(self):
# Given
invalid_document_data = {
"name": "Test Document",
"author": "John Doe",
"tag": "test"
# Missing 'page_count' field
}

# When / Then
with pytest.raises(ValidationError):
DocumentCreate(**invalid_document_data)

def test_invalid_document_create_wrong_type(self):
# Given
invalid_document_data = {
"name": "Test Document",
"author": "John Doe",
"tag": "test",
"page_count": "10" # Should be an integer, not a string
}

# When / Then
with pytest.raises(ValidationError) as exc_info:
DocumentCreate(**invalid_document_data)

# Additional assertion to check the error message
assert "Input should be a valid integer" in str(exc_info.value)

class TestDocumentResponseSchema:
def test_valid_document_response(self):
# Given
document_data = {
"id": "doc123",
"name": "Test Document",
"author": "John Doe",
"tag": "test",
"page_count": 10,
"created_at": datetime(2023, 4, 1, 12, 0, 0),
"updated_at": datetime(2023, 4, 1, 12, 0, 0)
}

# When
document = DocumentResponse(**document_data)

# Then
assert document.id == "doc123"
assert document.name == "Test Document"
assert document.author == "John Doe"
assert document.tag == "test"
assert document.page_count == 10

def test_document_response_inherits_from_document_model(self):
# Given / When
document_response = DocumentResponse

# Then
assert issubclass(document_response, Document)

class TestDeleteDocumentResponseSchema:
def test_valid_delete_document_response(self):
# Given
delete_response_data = {
"id": "doc123",
"status": "success",
"message": "Document deleted successfully"
}

# When
delete_response = DeleteDocumentResponse(**delete_response_data)

# Then
assert delete_response.id == "doc123"
assert delete_response.status == "success"
assert delete_response.message == "Document deleted successfully"

def test_invalid_delete_document_response_missing_field(self):
# Given
invalid_delete_response_data = {
"id": "doc123",
"status": "success"
# Missing 'message' field
}

# When / Then
with pytest.raises(ValidationError):
DeleteDocumentResponse(**invalid_delete_response_data)
Loading

0 comments on commit a225f15

Please sign in to comment.