feat: 实现数据库迁移、搜索和分页功能
- 添加数据库迁移系统和初始用户表迁移 - 实现搜索功能模块和API - 实现分页功能支持 - 添加相关测试文件 - 更新项目配置和文档
This commit is contained in:
352
tests/pagination_tests.rs
Normal file
352
tests/pagination_tests.rs
Normal file
@@ -0,0 +1,352 @@
|
||||
//! 分页功能专项测试
|
||||
|
||||
use rust_user_api::{
|
||||
models::{
|
||||
user::User,
|
||||
pagination::{PaginationParams, PaginatedResponse},
|
||||
search::UserSearchParams,
|
||||
},
|
||||
storage::{database::DatabaseUserStore, memory::MemoryUserStore, UserStore},
|
||||
utils::errors::ApiError,
|
||||
};
|
||||
use uuid::Uuid;
|
||||
use chrono::Utc;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// 创建测试用户
|
||||
fn create_test_user(username: &str, email: &str) -> User {
|
||||
User {
|
||||
id: Uuid::new_v4(),
|
||||
username: username.to_string(),
|
||||
email: email.to_string(),
|
||||
password_hash: "hashed_password".to_string(),
|
||||
created_at: Utc::now(),
|
||||
updated_at: Utc::now(),
|
||||
}
|
||||
}
|
||||
|
||||
/// 创建多个测试用户
|
||||
async fn create_multiple_users(store: &dyn UserStore, count: usize) -> Vec<User> {
|
||||
let mut users = Vec::new();
|
||||
|
||||
for i in 0..count {
|
||||
let user = create_test_user(
|
||||
&format!("user{:02}", i + 1),
|
||||
&format!("user{}@example.com", i + 1),
|
||||
);
|
||||
|
||||
let created_user = store.create_user(user).await.unwrap();
|
||||
users.push(created_user);
|
||||
|
||||
// 添加小延迟确保创建时间不同
|
||||
tokio::time::sleep(tokio::time::Duration::from_millis(1)).await;
|
||||
}
|
||||
|
||||
users
|
||||
}
|
||||
|
||||
/// 测试内存存储的分页功能
|
||||
#[tokio::test]
|
||||
async fn test_memory_store_pagination() {
|
||||
let store = MemoryUserStore::new();
|
||||
|
||||
// 创建15个用户
|
||||
let users = create_multiple_users(&store, 15).await;
|
||||
|
||||
// 测试第一页(每页5个)
|
||||
let params = PaginationParams {
|
||||
page: Some(1),
|
||||
limit: Some(5),
|
||||
};
|
||||
|
||||
let (paginated_users, total_count) = store.list_users_paginated(¶ms).await.unwrap();
|
||||
|
||||
assert_eq!(total_count, 15, "总用户数应该是15");
|
||||
assert_eq!(paginated_users.len(), 5, "第一页应该有5个用户");
|
||||
|
||||
// 测试第二页
|
||||
let params = PaginationParams {
|
||||
page: Some(2),
|
||||
limit: Some(5),
|
||||
};
|
||||
|
||||
let (paginated_users, total_count) = store.list_users_paginated(¶ms).await.unwrap();
|
||||
|
||||
assert_eq!(total_count, 15, "总用户数应该是15");
|
||||
assert_eq!(paginated_users.len(), 5, "第二页应该有5个用户");
|
||||
|
||||
// 测试第三页
|
||||
let params = PaginationParams {
|
||||
page: Some(3),
|
||||
limit: Some(5),
|
||||
};
|
||||
|
||||
let (paginated_users, total_count) = store.list_users_paginated(¶ms).await.unwrap();
|
||||
|
||||
assert_eq!(total_count, 15, "总用户数应该是15");
|
||||
assert_eq!(paginated_users.len(), 5, "第三页应该有5个用户");
|
||||
|
||||
// 测试第四页(超出范围)
|
||||
let params = PaginationParams {
|
||||
page: Some(4),
|
||||
limit: Some(5),
|
||||
};
|
||||
|
||||
let (paginated_users, total_count) = store.list_users_paginated(¶ms).await.unwrap();
|
||||
|
||||
assert_eq!(total_count, 15, "总用户数应该是15");
|
||||
assert_eq!(paginated_users.len(), 0, "第四页应该没有用户");
|
||||
}
|
||||
|
||||
/// 测试数据库存储的分页功能
|
||||
#[tokio::test]
|
||||
async fn test_database_store_pagination() {
|
||||
let database_url = "sqlite::memory:";
|
||||
let store = DatabaseUserStore::from_url(database_url).await.unwrap();
|
||||
|
||||
// 创建12个用户
|
||||
let users = create_multiple_users(&store, 12).await;
|
||||
|
||||
// 测试第一页(每页4个)
|
||||
let params = PaginationParams {
|
||||
page: Some(1),
|
||||
limit: Some(4),
|
||||
};
|
||||
|
||||
let (paginated_users, total_count) = store.list_users_paginated(¶ms).await.unwrap();
|
||||
|
||||
assert_eq!(total_count, 12, "总用户数应该是12");
|
||||
assert_eq!(paginated_users.len(), 4, "第一页应该有4个用户");
|
||||
|
||||
// 验证排序(应该按创建时间倒序)
|
||||
for i in 0..paginated_users.len() - 1 {
|
||||
assert!(
|
||||
paginated_users[i].created_at >= paginated_users[i + 1].created_at,
|
||||
"用户应该按创建时间倒序排列"
|
||||
);
|
||||
}
|
||||
|
||||
// 测试最后一页
|
||||
let params = PaginationParams {
|
||||
page: Some(3),
|
||||
limit: Some(4),
|
||||
};
|
||||
|
||||
let (paginated_users, total_count) = store.list_users_paginated(¶ms).await.unwrap();
|
||||
|
||||
assert_eq!(total_count, 12, "总用户数应该是12");
|
||||
assert_eq!(paginated_users.len(), 4, "第三页应该有4个用户");
|
||||
}
|
||||
|
||||
/// 测试分页参数的默认值和边界情况
|
||||
#[tokio::test]
|
||||
async fn test_pagination_params_edge_cases() {
|
||||
let store = MemoryUserStore::new();
|
||||
|
||||
// 创建8个用户
|
||||
create_multiple_users(&store, 8).await;
|
||||
|
||||
// 测试默认参数
|
||||
let params = PaginationParams {
|
||||
page: None,
|
||||
limit: None,
|
||||
};
|
||||
|
||||
let (paginated_users, total_count) = store.list_users_paginated(¶ms).await.unwrap();
|
||||
|
||||
assert_eq!(total_count, 8, "总用户数应该是8");
|
||||
assert_eq!(paginated_users.len(), 8, "默认应该返回所有用户(限制为10)");
|
||||
|
||||
// 测试页码为0(应该被修正为1)
|
||||
let params = PaginationParams {
|
||||
page: Some(0),
|
||||
limit: Some(3),
|
||||
};
|
||||
|
||||
let (paginated_users, total_count) = store.list_users_paginated(¶ms).await.unwrap();
|
||||
|
||||
assert_eq!(total_count, 8, "总用户数应该是8");
|
||||
assert_eq!(paginated_users.len(), 3, "页码0应该被修正为1,返回3个用户");
|
||||
|
||||
// 测试超大限制(应该被限制为100)
|
||||
let params = PaginationParams {
|
||||
page: Some(1),
|
||||
limit: Some(200),
|
||||
};
|
||||
|
||||
let (paginated_users, total_count) = store.list_users_paginated(¶ms).await.unwrap();
|
||||
|
||||
assert_eq!(total_count, 8, "总用户数应该是8");
|
||||
assert_eq!(paginated_users.len(), 8, "应该返回所有8个用户(限制为100)");
|
||||
|
||||
// 测试限制为0(应该被修正为1)
|
||||
let params = PaginationParams {
|
||||
page: Some(1),
|
||||
limit: Some(0),
|
||||
};
|
||||
|
||||
let (paginated_users, total_count) = store.list_users_paginated(¶ms).await.unwrap();
|
||||
|
||||
assert_eq!(total_count, 8, "总用户数应该是8");
|
||||
assert_eq!(paginated_users.len(), 1, "限制0应该被修正为1");
|
||||
}
|
||||
|
||||
/// 测试空数据库的分页
|
||||
#[tokio::test]
|
||||
async fn test_pagination_empty_database() {
|
||||
let store = MemoryUserStore::new();
|
||||
|
||||
let params = PaginationParams {
|
||||
page: Some(1),
|
||||
limit: Some(10),
|
||||
};
|
||||
|
||||
let (paginated_users, total_count) = store.list_users_paginated(¶ms).await.unwrap();
|
||||
|
||||
assert_eq!(total_count, 0, "空数据库总用户数应该是0");
|
||||
assert_eq!(paginated_users.len(), 0, "空数据库应该返回空列表");
|
||||
}
|
||||
|
||||
/// 测试搜索功能的分页
|
||||
#[tokio::test]
|
||||
async fn test_search_pagination() {
|
||||
let store = MemoryUserStore::new();
|
||||
|
||||
// 创建用户,其中一些包含"admin"
|
||||
let users = vec![
|
||||
create_test_user("admin1", "admin1@example.com"),
|
||||
create_test_user("user1", "user1@example.com"),
|
||||
create_test_user("admin2", "admin2@example.com"),
|
||||
create_test_user("user2", "user2@example.com"),
|
||||
create_test_user("admin3", "admin3@example.com"),
|
||||
create_test_user("user3", "user3@example.com"),
|
||||
];
|
||||
|
||||
for user in users {
|
||||
store.create_user(user).await.unwrap();
|
||||
}
|
||||
|
||||
// 搜索包含"admin"的用户,第一页
|
||||
let search_params = UserSearchParams {
|
||||
q: Some("admin".to_string()),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let pagination_params = PaginationParams {
|
||||
page: Some(1),
|
||||
limit: Some(2),
|
||||
};
|
||||
|
||||
let (search_results, total_count) = store.search_users(&search_params, &pagination_params).await.unwrap();
|
||||
|
||||
assert_eq!(total_count, 3, "应该找到3个admin用户");
|
||||
assert_eq!(search_results.len(), 2, "第一页应该返回2个用户");
|
||||
|
||||
// 验证搜索结果
|
||||
for user in &search_results {
|
||||
assert!(
|
||||
user.username.contains("admin") || user.email.contains("admin"),
|
||||
"搜索结果应该包含admin关键词"
|
||||
);
|
||||
}
|
||||
|
||||
// 搜索第二页
|
||||
let pagination_params = PaginationParams {
|
||||
page: Some(2),
|
||||
limit: Some(2),
|
||||
};
|
||||
|
||||
let (search_results, total_count) = store.search_users(&search_params, &pagination_params).await.unwrap();
|
||||
|
||||
assert_eq!(total_count, 3, "总数应该仍然是3");
|
||||
assert_eq!(search_results.len(), 1, "第二页应该返回1个用户");
|
||||
}
|
||||
|
||||
/// 测试PaginatedResponse结构
|
||||
#[tokio::test]
|
||||
async fn test_paginated_response_structure() {
|
||||
let store = MemoryUserStore::new();
|
||||
|
||||
// 创建7个用户
|
||||
create_multiple_users(&store, 7).await;
|
||||
|
||||
let params = PaginationParams {
|
||||
page: Some(2),
|
||||
limit: Some(3),
|
||||
};
|
||||
|
||||
let (users, total_count) = store.list_users_paginated(¶ms).await.unwrap();
|
||||
let response = PaginatedResponse::new(
|
||||
users.into_iter().map(|u| u.username).collect(),
|
||||
¶ms,
|
||||
total_count
|
||||
);
|
||||
|
||||
// 验证分页信息
|
||||
assert_eq!(response.pagination.current_page, 2);
|
||||
assert_eq!(response.pagination.per_page, 3);
|
||||
assert_eq!(response.pagination.total_pages, 3); // 7个用户,每页3个,共3页
|
||||
assert_eq!(response.pagination.total_items, 7);
|
||||
assert!(response.pagination.has_prev, "第二页应该有上一页");
|
||||
assert!(response.pagination.has_next, "第二页应该有下一页");
|
||||
|
||||
// 测试第一页
|
||||
let params = PaginationParams {
|
||||
page: Some(1),
|
||||
limit: Some(3),
|
||||
};
|
||||
|
||||
let (users, total_count) = store.list_users_paginated(¶ms).await.unwrap();
|
||||
let response = PaginatedResponse::new(
|
||||
users.into_iter().map(|u| u.username).collect(),
|
||||
¶ms,
|
||||
total_count
|
||||
);
|
||||
|
||||
assert!(!response.pagination.has_prev, "第一页不应该有上一页");
|
||||
assert!(response.pagination.has_next, "第一页应该有下一页");
|
||||
|
||||
// 测试最后一页
|
||||
let params = PaginationParams {
|
||||
page: Some(3),
|
||||
limit: Some(3),
|
||||
};
|
||||
|
||||
let (users, total_count) = store.list_users_paginated(¶ms).await.unwrap();
|
||||
let response = PaginatedResponse::new(
|
||||
users.into_iter().map(|u| u.username).collect(),
|
||||
¶ms,
|
||||
total_count
|
||||
);
|
||||
|
||||
assert!(response.pagination.has_prev, "最后一页应该有上一页");
|
||||
assert!(!response.pagination.has_next, "最后一页不应该有下一页");
|
||||
assert_eq!(response.data.len(), 1, "最后一页应该有1个用户");
|
||||
}
|
||||
|
||||
/// 测试分页功能的性能(大数据量)
|
||||
#[tokio::test]
|
||||
async fn test_pagination_performance() {
|
||||
let store = MemoryUserStore::new();
|
||||
|
||||
// 创建100个用户
|
||||
create_multiple_users(&store, 100).await;
|
||||
|
||||
let start = std::time::Instant::now();
|
||||
|
||||
// 测试获取中间页面的性能
|
||||
let params = PaginationParams {
|
||||
page: Some(50),
|
||||
limit: Some(2),
|
||||
};
|
||||
|
||||
let (paginated_users, total_count) = store.list_users_paginated(¶ms).await.unwrap();
|
||||
|
||||
let duration = start.elapsed();
|
||||
|
||||
assert_eq!(total_count, 100, "总用户数应该是100");
|
||||
assert_eq!(paginated_users.len(), 2, "应该返回2个用户");
|
||||
|
||||
// 性能检查:应该在合理时间内完成(这里设置为100ms,实际应该更快)
|
||||
assert!(duration.as_millis() < 100, "分页查询应该在100ms内完成,实际用时: {:?}", duration);
|
||||
}
|
Reference in New Issue
Block a user