From 9fc626232cd416f7a47cea8023ba0535e535dc53 Mon Sep 17 00:00:00 2001 From: xfy Date: Mon, 15 Jun 2026 11:20:33 +0800 Subject: [PATCH] =?UTF-8?q?test(error):=20=E8=A1=A5=E5=85=A8=20AppError=20?= =?UTF-8?q?=E5=90=84=E5=8F=98=E4=BD=93=E7=9A=84=E6=B6=88=E6=81=AF=E8=BD=AC?= =?UTF-8?q?=E6=8D=A2=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原仅覆盖 Unauthorized/Forbidden/NotFound/DbConn/Query 五个变体, 补充: - Internal 变体的消息透传 - Transaction 变体的 SQL 细节隐藏(与 Query 行为一致) - 三类数据库错误统一返回中文通用提示的聚合断言 共 8 个测试,全部通过。 --- src/api/error.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/api/error.rs b/src/api/error.rs index e69e1cc..412fcd3 100644 --- a/src/api/error.rs +++ b/src/api/error.rs @@ -106,4 +106,34 @@ mod tests { let msg = err.to_string(); assert!(msg.contains("文章不存在"), "expected passthrough: {msg}"); } + + #[test] + fn internal_message_passthrough() { + // Internal 错误的消息原样透传,便于向用户展示可读的内部错误描述。 + let err: ServerFnError = AppError::Internal("内部错误").into(); + let msg = err.to_string(); + assert!(msg.contains("内部错误"), "expected passthrough: {msg}"); + } + + #[test] + fn transaction_hides_sql_details() { + // 事务错误同样返回通用提示,不泄露 SQL 细节。 + let err: ServerFnError = AppError::tx("deadlock detected on UPDATE posts").into(); + let msg = err.to_string(); + assert!(!msg.contains("UPDATE"), "should not leak SQL: {msg}"); + assert!(!msg.contains("deadlock"), "should not leak error detail: {msg}"); + assert!(msg.contains("操作失败"), "expected generic message: {msg}"); + } + + #[test] + fn db_conn_query_transaction_all_return_generic_message() { + // 三类数据库错误对外均返回固定中文提示,避免泄露实现细节。 + let db_conn: ServerFnError = AppError::DbConn("x".into()).into(); + let query: ServerFnError = AppError::Query("x".into()).into(); + let tx: ServerFnError = AppError::Transaction("x".into()).into(); + + assert!(db_conn.to_string().contains("服务暂时不可用")); + assert!(query.to_string().contains("操作失败")); + assert!(tx.to_string().contains("操作失败")); + } }