如何在无法触发异常时测试异常处理?
我正在做一个Django REST框架(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的动作方法时,如果无法在测试中触发异常,有没有其他方法或最佳实践来测试异常处理?
关于测试异常处理的任何建议或见解都将非常感激。谢谢!
1 个回答
1
最简单的解决办法是把这个问题分成两个方法来处理:
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)
...