feat: 实现核心匹配引擎与请求处理器并修复解析逻辑

- 新增 router 模块:实现基于路径首段索引子集匹配。
- 新增 handler 模块:集成 Axum 处理器,支持 Smart Body 协议与延迟模拟。
- 修复解析与匹配故障:修正 YAML 字段类型解析错误。
This commit is contained in:
CNWei
2025-12-26 15:21:03 +08:00
parent 748cfa8e7f
commit 1775d3659d
9 changed files with 497 additions and 9 deletions

View File

@@ -2,8 +2,10 @@ use std::fs::{self, File};
use std::io::Write;
use tempfile::tempdir;
// 替换为你的项目实际名称
use mock_server::config::{MockSource, MockRule};
use mock_server::config::{MockRule, MockSource};
use mock_server::loader::MockLoader;
use mock_server::router::MockRouter;
use std::collections::HashMap;
/// 模块一:验证 Config 反序列化逻辑
#[test]
@@ -65,10 +67,81 @@ fn test_loader_recursive_indexing() {
// 验证逻辑:
// 即使物理路径很深,索引 Key 必须是逻辑路径的首段
assert!(index.contains_key("api"), "必须通过 /api/v1/login 提取出 'api' 键");
assert!(index.contains_key("health"), "必须通过 /health 提取出 'health' 键");
assert!(
index.contains_key("api"),
"必须通过 /api/v1/login 提取出 'api' 键"
);
assert!(
index.contains_key("health"),
"必须通过 /health 提取出 'health' 键"
);
// 验证扁平化后的总数
let total: usize = index.values().map(|v| v.len()).sum();
assert_eq!(total, 2);
}
}
#[test]
fn test_router_matching_logic() {
// 1. 准备模拟数据(模拟 Loader 的输出)
let mut index = HashMap::new();
let rule_auth = serde_yaml::from_str::<MockSource>(
r#"
id: "auth_v1"
request:
method: "POST"
path: "/api/v1/login"
headers: { "Content-Type": "application/json" }
response: { status: 200, body: "token_123" }
"#,
)
.unwrap()
.flatten();
let rule_user = serde_yaml::from_str::<MockSource>(
r#"
id: "get_user"
request:
method: "GET"
path: "/api/user/info"
query_params: { "id": "100" }
response: { status: 200, body: "user_info" }
"#,
)
.unwrap()
.flatten();
// 构建 HashMap 索引(模仿 Loader 的行为)
index.insert(
"api".to_string(),
vec![rule_auth[0].clone(), rule_user[0].clone()],
);
let router = MockRouter::new(index);
// 2. 测试场景 A完全匹配
let mut headers = HashMap::new();
headers.insert("Content-Type".to_string(), "application/json".to_string());
let matched = router.match_rule("POST", "/api/v1/login", &HashMap::new(), &headers);
assert!(matched.is_some());
assert_eq!(matched.unwrap().id, "auth_v1");
// 3. 测试场景 B路径末尾斜杠归一化 (Trailing Slash)
let matched_slash = router.match_rule("POST", "/api/v1/login/", &HashMap::new(), &headers);
assert!(matched_slash.is_some(), "应该忽略路径末尾的斜杠");
// 4. 测试场景 CQuery 参数子集匹配
let mut queries = HashMap::new();
queries.insert("id".to_string(), "100".to_string());
queries.insert("extra".to_string(), "unused".to_string()); // 额外的参数不应影响匹配
let matched_query = router.match_rule("GET", "/api/user/info", &queries, &HashMap::new());
assert!(matched_query.is_some());
assert_eq!(matched_query.unwrap().id, "get_user");
// 5. 测试场景 D匹配失败Method 错误)
let fail_method = router.match_rule("GET", "/api/v1/login", &HashMap::new(), &headers);
assert!(fail_method.is_none());
}