Skip to content

Commit

Permalink
Add tests for exception handler
Browse files Browse the repository at this point in the history
  • Loading branch information
samarpan1738 committed Dec 22, 2024
1 parent 4220a2c commit 4190896
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 0 deletions.
1 change: 1 addition & 0 deletions todo/tests/unit/exceptions/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Added this because without this file Django isn't able to auto detect the test files
73 changes: 73 additions & 0 deletions todo/tests/unit/exceptions/test_exception_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
from unittest import TestCase
from unittest.mock import Mock, patch
from rest_framework.exceptions import ValidationError
from rest_framework.response import Response
from rest_framework import status

from todo.exceptions.exception_handler import handle_exception, format_validation_errors
from todo.dto.responses.error_response import ApiErrorDetail, ApiErrorSource


class ExceptionHandlerTests(TestCase):
@patch("todo.exceptions.exception_handler.format_validation_errors")
def test_returns_400_for_validation_error(self, mock_format_validation_errors: Mock):
validation_error = ValidationError(detail={"field": ["error message"]})
mock_format_validation_errors.return_value = [
ApiErrorDetail(detail="error message", source={ApiErrorSource.PARAMETER: "field"})
]

response = handle_exception(validation_error, {})

self.assertIsInstance(response, Response)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
expected_response = {
"statusCode": 400,
"message": "Invalid request",
"errors": [{"source": {"parameter": "field"}, "detail": "error message"}],
}
self.assertDictEqual(response.data, expected_response)

mock_format_validation_errors.assert_called_once_with(validation_error.detail)

def test_uses_default_handler_for_non_validation_error(self):
generic_exception = ValueError("Something went wrong")

response = handle_exception(generic_exception, {})
self.assertIsNone(response)


class FormatValidationErrorsTests(TestCase):
def test_formats_flat_validation_errors(self):
errors = {"field": ["error message 1", "error message 2"]}
expected_result = [
ApiErrorDetail(detail="error message 1", source={ApiErrorSource.PARAMETER: "field"}),
ApiErrorDetail(detail="error message 2", source={ApiErrorSource.PARAMETER: "field"}),
]

result = format_validation_errors(errors)

self.assertEqual(result, expected_result)

def test_formats_nested_validation_errors(self):
errors = {
"parent_field": {
"child_field": ["child error message"],
"another_child": {"deep_field": ["deep error message"]},
}
}
expected_result = [
ApiErrorDetail(detail="child error message", source={ApiErrorSource.PARAMETER: "child_field"}),
ApiErrorDetail(detail="deep error message", source={ApiErrorSource.PARAMETER: "deep_field"}),
]

result = format_validation_errors(errors)

self.assertEqual(result, expected_result)

def test_formats_non_list_dict_validation_error(self):
errors = {"field": "Not a list or dict"}
expected_result = [ApiErrorDetail(detail="Not a list or dict", source={ApiErrorSource.PARAMETER: "field"})]

result = format_validation_errors(errors)

self.assertEqual(result, expected_result)

0 comments on commit 4190896

Please sign in to comment.