Files
rust-user-api/tests/pagination_tests.rs
enoch cf01d557b9 feat: 实现数据库迁移、搜索和分页功能
- 添加数据库迁移系统和初始用户表迁移
- 实现搜索功能模块和API
- 实现分页功能支持
- 添加相关测试文件
- 更新项目配置和文档
2025-08-05 23:44:01 +08:00

352 lines
11 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! 分页功能专项测试
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(&params).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(&params).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(&params).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(&params).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(&params).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(&params).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(&params).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(&params).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(&params).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(&params).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(&params).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(&params).await.unwrap();
let response = PaginatedResponse::new(
users.into_iter().map(|u| u.username).collect(),
&params,
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(&params).await.unwrap();
let response = PaginatedResponse::new(
users.into_iter().map(|u| u.username).collect(),
&params,
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(&params).await.unwrap();
let response = PaginatedResponse::new(
users.into_iter().map(|u| u.username).collect(),
&params,
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(&params).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);
}