Files
meijiaka-zy/python-api/tests/test_exceptions.py
T

117 lines
3.7 KiB
Python

"""
异常体系单元测试
================
验证 AppException / InsufficientPointsException 的结构化字段,
确保前端可以通过 error_code 识别错误类型。
"""
from fastapi import HTTPException
from app.core.exceptions import (
AIEmptyResponseException,
AIParseErrorException,
AITimeoutException,
AppException,
BusinessException,
InsufficientPointsException,
NotFoundException,
PromptNotFoundException,
ValidationException,
)
class TestAppException:
"""业务异常基类"""
def test_app_exception_has_error_code(self) -> None:
exc = AppException(
status_code=400,
message="参数错误",
error_code="validation_error",
)
assert exc.status_code == 400
assert exc.message == "参数错误"
assert exc.error_code == "validation_error"
assert exc.detail == {"message": "参数错误", "error_code": "validation_error"}
def test_app_exception_detail_can_be_dict(self) -> None:
exc = AppException(
status_code=422,
message="字段校验失败",
detail={"fields": {"name": "required"}},
error_code="validation_error",
)
assert exc.detail == {
"fields": {"name": "required"},
"message": "字段校验失败",
"error_code": "validation_error",
}
def test_subclasses_without_error_code(self) -> None:
exc = NotFoundException("资源不存在")
assert exc.status_code == 404
assert exc.message == "资源不存在"
assert exc.error_code is None
class TestInsufficientPointsException:
"""积分不足异常"""
def test_default_fields(self) -> None:
exc = InsufficientPointsException()
assert exc.status_code == 402
assert exc.message == "积分不足"
assert exc.error_code == "insufficient_points"
assert isinstance(exc, HTTPException)
def test_custom_message(self) -> None:
exc = InsufficientPointsException("余额不足,请先充值")
assert exc.message == "余额不足,请先充值"
assert exc.error_code == "insufficient_points"
def test_detail_structure(self) -> None:
exc = InsufficientPointsException("需要 10 积分")
assert exc.detail == {
"message": "需要 10 积分",
"error_code": "insufficient_points",
}
class TestOtherSubclasses:
"""其他常用子类"""
def test_validation_exception(self) -> None:
exc = ValidationException("字段缺失")
assert exc.status_code == 422
assert exc.message == "字段缺失"
def test_business_exception(self) -> None:
exc = BusinessException("业务状态不允许")
assert exc.status_code == 400
assert exc.message == "业务状态不允许"
class TestAIStructuredExceptions:
"""AI 相关结构化异常"""
def test_prompt_not_found_exception(self) -> None:
exc = PromptNotFoundException("未找到提示词")
assert exc.status_code == 404
assert exc.error_code == "prompt_not_found"
def test_ai_empty_response_exception(self) -> None:
exc = AIEmptyResponseException("AI 返回为空")
assert exc.status_code == 500
assert exc.error_code == "empty_result"
def test_ai_parse_error_exception(self) -> None:
exc = AIParseErrorException("解析失败")
assert exc.status_code == 500
assert exc.error_code == "parse_error"
def test_ai_timeout_exception(self) -> None:
exc = AITimeoutException("请求超时")
assert exc.status_code == 504
assert exc.error_code == "timeout"