Files

144 lines
4.8 KiB
Python
Raw Permalink Normal View History

# =============================================================================
# 企微IT智能服务台 — API 基础验证测试
# =============================================================================
# 测试覆盖:
# 1. 健康检查端点
# 2. 统一响应格式(code/data/message
# 3. CORS 配置
# 4. 404 路由
# 5. AppException 全局异常处理
# 6. success_response / error_response 工具函数
# =============================================================================
import pytest
import pytest_asyncio
from app.utils.response import success_response, error_response, AppException
class TestHealthCheck:
"""测试健康检查端点。"""
@pytest.mark.asyncio
async def test_health_check(self, client, db_session):
"""验证 /health 端点返回正常状态。"""
response = await client.get("/health")
assert response.status_code == 200
data = response.json()
assert data["status"] == "ok"
assert "service" in data
class TestUnifiedResponseFormat:
"""测试统一响应格式。"""
def test_success_response_format(self):
"""验证成功响应格式:{code: 0, data: {}, message: "success"}。"""
result = success_response(data={"key": "value"})
assert result["code"] == 0
assert result["data"] == {"key": "value"}
assert result["message"] == "success"
def test_success_response_default_data(self):
"""验证成功响应默认 data 为 None。"""
result = success_response()
assert result["code"] == 0
assert result["data"] is None
def test_success_response_custom_message(self):
"""验证成功响应自定义消息。"""
result = success_response(message="操作成功")
assert result["message"] == "操作成功"
def test_error_response_format(self):
"""验证错误响应格式:{code: N, data: null, message: "错误信息"}。"""
result = error_response(1001, "参数错误")
assert result["code"] == 1001
assert result["data"] is None
assert result["message"] == "参数错误"
def test_error_response_with_data(self):
"""验证错误响应可附带额外数据。"""
result = error_response(1001, "校验失败", data={"field": "email"})
assert result["data"] == {"field": "email"}
class TestAppException:
"""测试业务异常类。"""
def test_app_exception_attributes(self):
"""验证 AppException 包含 code/message/data 属性。"""
exc = AppException(1002, "未授权")
assert exc.code == 1002
assert exc.message == "未授权"
assert exc.data is None
def test_app_exception_with_data(self):
"""验证 AppException 可附带数据。"""
exc = AppException(1001, "参数错误", data={"field": "id"})
assert exc.data == {"field": "id"}
def test_app_exception_is_exception(self):
"""验证 AppException 是 Exception 的子类。"""
exc = AppException(1001, "测试")
assert isinstance(exc, Exception)
def test_predefined_error_constants(self):
"""验证预定义错误常量。"""
from app.utils.response import (
ERR_PARAMS, ERR_UNAUTHORIZED, ERR_NOT_FOUND,
ERR_FORBIDDEN, ERR_INTERNAL,
)
assert ERR_PARAMS.code == 1001
assert ERR_UNAUTHORIZED.code == 1002
assert ERR_NOT_FOUND.code == 1003
assert ERR_FORBIDDEN.code == 1004
assert ERR_INTERNAL.code == 1005
class TestAPIRoutes:
"""测试 API 路由基础。"""
@pytest.mark.asyncio
async def test_404_not_found(self, client, db_session):
"""验证访问不存在的路由返回 404。"""
response = await client.get("/nonexistent-route")
assert response.status_code == 404
@pytest.mark.asyncio
async def test_api_prefix(self, client, db_session):
"""验证 API 路径前缀为 /api。"""
# /api/agents 是有效路由
response = await client.get("/agents")
assert response.status_code == 200
@pytest.mark.asyncio
async def test_conversations_list_response_format(self, client, db_session, mock_redis):
"""验证会话列表 API 返回统一响应格式。"""
# 先登录坐席获取 token/api/conversations 需要 get_current_agent 认证)
login_resp = await client.post(
"/agents/login",
json={"user_id": "basic_test_agent", "name": "基础测试坐席"},
)
token = login_resp.json()["data"]["token"]
response = await client.get(
"/conversations",
headers={"Authorization": f"Bearer {token}"},
)
data = response.json()
assert "code" in data
assert "data" in data
assert "message" in data
assert data["code"] == 0