Files
rust-user-api/tests/pagination_tests.rs
enoch bb9d7a869d
Some checks failed
Deploy to Production / Run Tests (push) Failing after 16m35s
Deploy to Production / Security Scan (push) Has been skipped
Deploy to Production / Build Docker Image (push) Has been skipped
Deploy to Production / Deploy to Staging (push) Has been skipped
Deploy to Production / Deploy to Production (push) Has been skipped
Deploy to Production / Notify Results (push) Successful in 31s
feat: 完成Rust User API完整开发
 新功能:
- SQLite数据库集成和持久化存储
- 数据库迁移系统和版本管理
- API分页功能和高效查询
- 用户搜索和过滤机制
- 完整的RBAC角色权限系统
- 结构化日志记录和系统监控
- API限流和多层安全防护
- Docker容器化和生产部署配置

🔒 安全特性:
- JWT认证和授权
- 限流和防暴力破解
- 安全头和CORS配置
- 输入验证和XSS防护
- 审计日志和安全监控

📊 监控和运维:
- Prometheus指标收集
- 健康检查和系统监控
- 自动化备份和恢复
- 完整的运维文档和脚本
- CI/CD流水线配置

🚀 部署支持:
- 多环境Docker配置
- 生产环境部署指南
- 性能优化和安全加固
- 故障排除和应急响应
- 自动化运维脚本

📚 文档完善:
- API使用文档
- 部署检查清单
- 运维操作手册
- 性能和安全指南
- 故障排除指南
2025-08-07 16:03:32 +08:00

354 lines
11 KiB
Rust
Raw Permalink 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,
role::UserRole,
},
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(),
role: UserRole::User,
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);
}