Как протестировать обработку исключений, если не удается вызвать исключение во время тестирования?
Я работаю над набором представлений Django REST Framework (DRF), который включает обработку исключений для решения непредвиденных ошибок. В наборе представлений есть метод действия, который извлекает информацию о ценах на серверах из стороннего API. Вот упрощенная версия кода:
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import status
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
import logging
logger = logging.getLogger(__name__)
class MyViewSet(viewsets.ViewSet):
@action(detail=False, methods=["get"], url_path="pricing", authentication_classes=[])
@method_decorator(csrf_exempt) # For testing purposes only
def pricing(self, request, pk=None):
""" List all pricing or a specific server """
try:
server_type = request.query_params.get("server_type")
location = request.query_params.get("location")
# Case 1: returns the pricing list
if not server_type or not location:
pricing = self.hapi.pricing()
return Response(pricing, status=status.HTTP_200_OK)
# Case 2: returns the pricing of the provided server info
prices = self.hapi.calculate_price(server_type, location)
return Response(prices, status=status.HTTP_200_OK)
except Exception as error:
logger.critical(f"Error fetching server pricing: {error}", exc_info=True)
return Response({"message": "Error fetching server pricing", "error": str(error)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
Я пытаюсь протестировать часть кода except Exception, но у меня возникают проблемы с вызовом исключения во время тестирования. Поскольку путь кода, ведущий к исключению, сложно воспроизвести в контролируемой среде тестирования, я не уверен, как эффективно протестировать логику обработки исключений.
Вот что я пробовал до сих пор:
def test_prices_exception(self, mocker, client):
""" if pricing raised any exception """
exception_error = "mock error"
mocker.patch("core.views.datacenter.abc.abcVPS.pricing",
side_effect=Exception(exception_error))
mock_logger = mocker.patch(
"core.views.datacenter.abc.logger")
url = SERVER_PRICE_URL
response = client.get(url)
assert "message" in response.data
assert "error" in response.data
assert mock_logger.critical.wrap_assert_called_once_with(
f"Error fetching server pricing: {exception_error}")
assert response.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR
здесь я подражаю самому методу (pricing), что приводит к ошибке. и я также не могу пойти дальше, чтобы подражать чему-то внутри метода 'pricing'. или, может быть, я просто не знаю, как это сделать... нужно ли вообще тестировать что-то подобное?
- Как проверить часть кода except Exception, если во время тестирования сложно вызвать исключение?
- Есть ли у вас какие-либо советы или приемы для имитации условий, которые приведут к возникновению исключения в контролируемой среде тестирования?
- Существуют ли альтернативные подходы или лучшие практики для тестирования обработки исключений в методах действий DRF, когда не представляется возможным вызвать исключение во время тестирования?
Любые советы или соображения по тестированию обработки исключений будут очень признательны. Большое спасибо!
Самое наивное решение: вы можете разделить это на два метода:
def pricing(self, request, pk=None):
""" List all pricing or a specific server """
try:
self._pricing(request, pk)
except Exception as error:
logger.critical(f"Error fetching server pricing: {error}", exc_info=True)
return Response({"message": "Error fetching server pricing", "error": str(error)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
def _pricing(self, request, pk):
server_type = request.query_params.get("server_type")
location = request.query_params.get("location")
# Case 1: returns the pricing list
if not server_type or not location:
pricing = self.hapi.pricing()
return Response(pricing, status=status.HTTP_200_OK)
# Case 2: returns the pricing of the provided server info
prices = self.hapi.calculate_price(server_type, location)
return Response(prices, status=status.HTTP_200_OK)
Чтобы протестировать обработку исключений, вам нужно лишь подружить метод _pricing
с побочным эффектом.
def test():
with mock.patch("path.to._pricing", new=Mock(side_effect=Exception(exception_error))):
response = client.get(url)
...