# ============================================================================= # 企微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