275 lines
9.5 KiB
Rust
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);
|
|
}
|
|
} |