我正在开发一个 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
这里我嘲笑方法本身(定价),这会导致错误。我也无法进一步嘲笑“定价”方法中的某些内容。或者也许我只是不知道如何... 有必要测试这样的东西吗?
任何有关测试异常处理的建议或见解将不胜感激。非常感谢!
最天真的解决方案:您可以将其分为两种方法:
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)
...