Test coverage increased from ~34 to 183 tests (zero failures): - erp-core (21): version check, pagination, API response, error mapping - erp-auth (39): org tree building, DTO validation, error conversion, password hashing, user model mapping - erp-config (57): DTO validation, numbering reset logic, menu tree building, error conversion. Fixed BatchSaveMenusReq nested validation - erp-message (50): DTO validation, template rendering, query defaults, error conversion - erp-workflow (16): unchanged (parser + expression tests) All tests are pure unit tests requiring no database.
117 lines
4.2 KiB
Rust
117 lines
4.2 KiB
Rust
use erp_core::error::AppError;
|
||
|
||
/// Config module error types.
|
||
#[derive(Debug, thiserror::Error)]
|
||
pub enum ConfigError {
|
||
#[error("验证失败: {0}")]
|
||
Validation(String),
|
||
|
||
#[error("资源未找到: {0}")]
|
||
NotFound(String),
|
||
|
||
#[error("键已存在: {0}")]
|
||
DuplicateKey(String),
|
||
|
||
#[error("编号序列耗尽: {0}")]
|
||
NumberingExhausted(String),
|
||
|
||
#[error("版本冲突: 数据已被其他操作修改,请刷新后重试")]
|
||
VersionMismatch,
|
||
}
|
||
|
||
impl From<sea_orm::TransactionError<ConfigError>> for ConfigError {
|
||
fn from(err: sea_orm::TransactionError<ConfigError>) -> Self {
|
||
match err {
|
||
sea_orm::TransactionError::Connection(err) => ConfigError::Validation(err.to_string()),
|
||
sea_orm::TransactionError::Transaction(inner) => inner,
|
||
}
|
||
}
|
||
}
|
||
|
||
impl From<ConfigError> for AppError {
|
||
fn from(err: ConfigError) -> Self {
|
||
match err {
|
||
ConfigError::Validation(s) => AppError::Validation(s),
|
||
ConfigError::NotFound(s) => AppError::NotFound(s),
|
||
ConfigError::DuplicateKey(s) => AppError::Conflict(s),
|
||
ConfigError::NumberingExhausted(s) => AppError::Internal(s),
|
||
ConfigError::VersionMismatch => AppError::VersionMismatch,
|
||
}
|
||
}
|
||
}
|
||
|
||
pub type ConfigResult<T> = Result<T, ConfigError>;
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
use erp_core::error::AppError;
|
||
|
||
#[test]
|
||
fn config_error_validation_maps_to_app_validation() {
|
||
let app: AppError = ConfigError::Validation("字段不能为空".to_string()).into();
|
||
match app {
|
||
AppError::Validation(msg) => assert_eq!(msg, "字段不能为空"),
|
||
other => panic!("期望 Validation,实际得到 {:?}", other),
|
||
}
|
||
}
|
||
|
||
#[test]
|
||
fn config_error_not_found_maps_to_app_not_found() {
|
||
let app: AppError = ConfigError::NotFound("字典不存在".to_string()).into();
|
||
match app {
|
||
AppError::NotFound(msg) => assert_eq!(msg, "字典不存在"),
|
||
other => panic!("期望 NotFound,实际得到 {:?}", other),
|
||
}
|
||
}
|
||
|
||
#[test]
|
||
fn config_error_duplicate_key_maps_to_app_conflict() {
|
||
let app: AppError = ConfigError::DuplicateKey("编码已存在".to_string()).into();
|
||
match app {
|
||
AppError::Conflict(msg) => assert_eq!(msg, "编码已存在"),
|
||
other => panic!("期望 Conflict,实际得到 {:?}", other),
|
||
}
|
||
}
|
||
|
||
#[test]
|
||
fn config_error_numbering_exhausted_maps_to_app_internal() {
|
||
let app: AppError = ConfigError::NumberingExhausted("序列已耗尽".to_string()).into();
|
||
match app {
|
||
AppError::Internal(msg) => assert!(msg.contains("序列已耗尽")),
|
||
other => panic!("期望 Internal,实际得到 {:?}", other),
|
||
}
|
||
}
|
||
|
||
#[test]
|
||
fn config_error_version_mismatch_maps_to_app_version_mismatch() {
|
||
let app: AppError = ConfigError::VersionMismatch.into();
|
||
match app {
|
||
AppError::VersionMismatch => {}
|
||
other => panic!("期望 VersionMismatch,实际得到 {:?}", other),
|
||
}
|
||
}
|
||
|
||
#[test]
|
||
fn config_error_display_messages() {
|
||
// 验证各变体的 Display 输出包含中文描述
|
||
assert!(ConfigError::Validation("test".into()).to_string().contains("验证失败"));
|
||
assert!(ConfigError::NotFound("test".into()).to_string().contains("资源未找到"));
|
||
assert!(ConfigError::DuplicateKey("test".into()).to_string().contains("键已存在"));
|
||
assert!(ConfigError::NumberingExhausted("test".into()).to_string().contains("编号序列耗尽"));
|
||
assert!(ConfigError::VersionMismatch.to_string().contains("版本冲突"));
|
||
}
|
||
|
||
#[test]
|
||
fn transaction_error_connection_maps_to_validation() {
|
||
// TransactionError::Connection 应该转换为 ConfigError::Validation
|
||
let config_err: ConfigError =
|
||
sea_orm::TransactionError::Connection(sea_orm::DbErr::Conn(sea_orm::RuntimeErr::Internal("连接失败".to_string())))
|
||
.into();
|
||
match config_err {
|
||
ConfigError::Validation(msg) => assert!(msg.contains("连接失败")),
|
||
other => panic!("期望 Validation,实际得到 {:?}", other),
|
||
}
|
||
}
|
||
}
|