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

275 lines
9.5 KiB
Rust

//! SQLite 数据库存储测试
use rust_user_api::{
models::user::User,
storage::{database::DatabaseUserStore, UserStore},
utils::errors::ApiError,
};
use uuid::Uuid;
use chrono::Utc;
use tempfile::tempdir;
/// 创建临时数据库用于测试
async fn create_test_database() -> Result<DatabaseUserStore, ApiError> {
// 使用内存数据库避免文件系统问题
let database_url = "sqlite::memory:";
DatabaseUserStore::from_url(database_url).await
}
/// 创建测试用户
fn create_test_user() -> User {
User {
id: Uuid::new_v4(),
username: "testuser".to_string(),
email: "test@example.com".to_string(),
password_hash: "hashed_password".to_string(),
created_at: Utc::now(),
updated_at: Utc::now(),
}
}
#[tokio::test]
async fn test_database_connection_and_initialization() {
let store = create_test_database().await;
assert!(store.is_ok(), "Failed to create database store");
}
#[tokio::test]
async fn test_database_create_user() {
let store = create_test_database().await.unwrap();
let user = create_test_user();
let result = store.create_user(user.clone()).await;
assert!(result.is_ok(), "Failed to create user: {:?}", result.err());
let created_user = result.unwrap();
assert_eq!(created_user.username, user.username);
assert_eq!(created_user.email, user.email);
assert_eq!(created_user.id, user.id);
}
#[tokio::test]
async fn test_database_get_user_by_id() {
let store = create_test_database().await.unwrap();
let user = create_test_user();
let user_id = user.id;
// 先创建用户
store.create_user(user.clone()).await.unwrap();
// 然后获取用户
let result = store.get_user(&user_id).await;
assert!(result.is_ok(), "Failed to get user: {:?}", result.err());
let retrieved_user = result.unwrap();
assert!(retrieved_user.is_some(), "User not found");
let retrieved_user = retrieved_user.unwrap();
assert_eq!(retrieved_user.id, user_id);
assert_eq!(retrieved_user.username, user.username);
assert_eq!(retrieved_user.email, user.email);
}
#[tokio::test]
async fn test_database_get_user_by_username() {
let store = create_test_database().await.unwrap();
let user = create_test_user();
let username = user.username.clone();
// 先创建用户
store.create_user(user.clone()).await.unwrap();
// 然后按用户名获取用户
let result = store.get_user_by_username(&username).await;
assert!(result.is_ok(), "Failed to get user by username: {:?}", result.err());
let retrieved_user = result.unwrap();
assert!(retrieved_user.is_some(), "User not found by username");
let retrieved_user = retrieved_user.unwrap();
assert_eq!(retrieved_user.username, username);
assert_eq!(retrieved_user.id, user.id);
}
#[tokio::test]
async fn test_database_list_users() {
let store = create_test_database().await.unwrap();
// 创建多个用户
let user1 = User {
id: Uuid::new_v4(),
username: "user1".to_string(),
email: "user1@example.com".to_string(),
password_hash: "hashed_password1".to_string(),
created_at: Utc::now(),
updated_at: Utc::now(),
};
let user2 = User {
id: Uuid::new_v4(),
username: "user2".to_string(),
email: "user2@example.com".to_string(),
password_hash: "hashed_password2".to_string(),
created_at: Utc::now(),
updated_at: Utc::now(),
};
store.create_user(user1.clone()).await.unwrap();
store.create_user(user2.clone()).await.unwrap();
// 获取所有用户
let result = store.list_users().await;
assert!(result.is_ok(), "Failed to list users: {:?}", result.err());
let users = result.unwrap();
assert_eq!(users.len(), 2, "Expected 2 users, got {}", users.len());
// 验证用户存在
let usernames: Vec<String> = users.iter().map(|u| u.username.clone()).collect();
assert!(usernames.contains(&"user1".to_string()));
assert!(usernames.contains(&"user2".to_string()));
}
#[tokio::test]
async fn test_database_update_user() {
let store = create_test_database().await.unwrap();
let mut user = create_test_user();
let user_id = user.id;
// 先创建用户
store.create_user(user.clone()).await.unwrap();
// 更新用户信息
user.username = "updated_user".to_string();
user.email = "updated@example.com".to_string();
user.updated_at = Utc::now();
let result = store.update_user(&user_id, user.clone()).await;
assert!(result.is_ok(), "Failed to update user: {:?}", result.err());
let updated_user = result.unwrap();
assert!(updated_user.is_some(), "Updated user not returned");
let updated_user = updated_user.unwrap();
assert_eq!(updated_user.username, "updated_user");
assert_eq!(updated_user.email, "updated@example.com");
// 验证数据库中的用户确实被更新了
let retrieved_user = store.get_user(&user_id).await.unwrap().unwrap();
assert_eq!(retrieved_user.username, "updated_user");
assert_eq!(retrieved_user.email, "updated@example.com");
}
#[tokio::test]
async fn test_database_delete_user() {
let store = create_test_database().await.unwrap();
let user = create_test_user();
let user_id = user.id;
// 先创建用户
store.create_user(user.clone()).await.unwrap();
// 验证用户存在
let user_exists = store.get_user(&user_id).await.unwrap();
assert!(user_exists.is_some(), "User should exist before deletion");
// 删除用户
let result = store.delete_user(&user_id).await;
assert!(result.is_ok(), "Failed to delete user: {:?}", result.err());
assert!(result.unwrap(), "Delete operation should return true");
// 验证用户已被删除
let user_after_delete = store.get_user(&user_id).await.unwrap();
assert!(user_after_delete.is_none(), "User should not exist after deletion");
}
#[tokio::test]
async fn test_database_duplicate_username_constraint() {
let store = create_test_database().await.unwrap();
let user1 = User {
id: Uuid::new_v4(),
username: "duplicate_test".to_string(),
email: "test1@example.com".to_string(),
password_hash: "hashed_password1".to_string(),
created_at: Utc::now(),
updated_at: Utc::now(),
};
let user2 = User {
id: Uuid::new_v4(),
username: "duplicate_test".to_string(), // 相同用户名
email: "test2@example.com".to_string(),
password_hash: "hashed_password2".to_string(),
created_at: Utc::now(),
updated_at: Utc::now(),
};
// 创建第一个用户应该成功
let result1 = store.create_user(user1).await;
assert!(result1.is_ok(), "First user creation should succeed");
// 创建第二个用户应该失败(用户名重复)
let result2 = store.create_user(user2).await;
assert!(result2.is_err(), "Second user creation should fail due to duplicate username");
if let Err(ApiError::Conflict(msg)) = result2 {
assert!(msg.contains("用户名已存在"), "Error message should mention duplicate username");
} else {
panic!("Expected Conflict error for duplicate username, got: {:?}", result2);
}
}
#[tokio::test]
async fn test_database_nonexistent_user_operations() {
let store = create_test_database().await.unwrap();
let nonexistent_id = Uuid::new_v4();
// 获取不存在的用户
let result = store.get_user(&nonexistent_id).await;
assert!(result.is_ok(), "Getting nonexistent user should not error");
assert!(result.unwrap().is_none(), "Nonexistent user should return None");
// 按用户名获取不存在的用户
let result = store.get_user_by_username("nonexistent_user").await;
assert!(result.is_ok(), "Getting nonexistent user by username should not error");
assert!(result.unwrap().is_none(), "Nonexistent user should return None");
// 更新不存在的用户
let fake_user = create_test_user();
let result = store.update_user(&nonexistent_id, fake_user).await;
assert!(result.is_ok(), "Updating nonexistent user should not error");
assert!(result.unwrap().is_none(), "Updating nonexistent user should return None");
// 删除不存在的用户
let result = store.delete_user(&nonexistent_id).await;
assert!(result.is_ok(), "Deleting nonexistent user should not error");
assert!(!result.unwrap(), "Deleting nonexistent user should return false");
}
#[tokio::test]
async fn test_database_data_persistence() {
let temp_dir = tempdir().expect("Failed to create temp directory");
let db_path = temp_dir.path().join("persistence_test.db");
let database_url = format!("sqlite://{}?mode=rwc", db_path.display());
let user = create_test_user();
let user_id = user.id;
// 第一次连接:创建用户
{
let store = DatabaseUserStore::from_url(&database_url).await.unwrap();
store.create_user(user.clone()).await.unwrap();
}
// 第二次连接:验证用户仍然存在
{
let store = DatabaseUserStore::from_url(&database_url).await.unwrap();
let retrieved_user = store.get_user(&user_id).await.unwrap();
assert!(retrieved_user.is_some(), "User should persist across connections");
let retrieved_user = retrieved_user.unwrap();
assert_eq!(retrieved_user.username, user.username);
assert_eq!(retrieved_user.email, user.email);
}
}