测试时无法触发异常,如何测试异常处理?

问题描述 投票:0回答:1

我正在开发一个 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

这里我嘲笑方法本身(定价),这会导致错误。我也无法进一步嘲笑“定价”方法中的某些内容。或者也许我只是不知道如何... 有必要测试这样的东西吗?

  • 当测试过程中很难引发异常时,如何测试代码中的 except Exception 部分?
  • 您是否有任何提示或技巧来模拟可能导致在受控测试环境中引发异常的条件?
  • 当在测试期间触发异常不可行时,是否有任何替代方法或最佳实践来测试 DRF 操作方法中的异常处理?

任何有关测试异常处理的建议或见解将不胜感激。非常感谢!

python django unit-testing django-rest-framework pytest
1个回答
0
投票

最天真的解决方案:您可以将其分为两种方法:

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)
        ...
© www.soinside.com 2019 - 2024. All rights reserved.