package model import ( "context" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gorm.io/driver/mysql" "gorm.io/gorm" ) // setupProfileModelTestDB 创建测试数据库(使用MySQL) func setupProfileModelTestDB(t *testing.T) *gorm.DB { t.Helper() // 使用 MySQL 进行测试 dsn := "root:dev123456@tcp(219.159.132.177:17173)/base?charset=utf8mb4&parseTime=true&loc=Local" db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) require.NoError(t, err) err = db.AutoMigrate(&User{}, &Profile{}) require.NoError(t, err) // 清理所有测试数据(TRUNCATE) db.Exec("SET FOREIGN_KEY_CHECKS = 0") db.Exec("TRUNCATE TABLE profile") db.Exec("TRUNCATE TABLE user") db.Exec("SET FOREIGN_KEY_CHECKS = 1") return db } // createTestUserProfile 创建测试用户和关联的个人资料 func createTestUserProfile(t *testing.T, db *gorm.DB) (int64, int64) { t.Helper() now := time.Now() // 创建用户 user := &User{ Username: "testuser", Email: "test@example.com", Password: "encryptedpassword", Phone: "13800138000", Status: 1, CreatedAt: now, UpdatedAt: now, } err := db.Create(user).Error require.NoError(t, err) // 创建个人资料 profile := &Profile{ UserId: user.Id, Avatar: "http://example.com/avatar.jpg", Bio: "Test bio", CreatedAt: now, UpdatedAt: now, } err = db.Create(profile).Error require.NoError(t, err) return user.Id, profile.Id } // TestInsertProfile 测试插入个人资料 func TestInsertProfile(t *testing.T) { db := setupProfileModelTestDB(t) ctx := context.Background() // 先创建用户 now := time.Now() user := &User{ Username: "testuser", Email: "test@example.com", Password: "encryptedpassword", Status: 1, CreatedAt: now, UpdatedAt: now, } err := db.Create(user).Error require.NoError(t, err) // 创建个人资料 profile := &Profile{ UserId: user.Id, Avatar: "http://example.com/avatar.jpg", Bio: "Test bio", } id, err := InsertProfile(ctx, db, profile) require.NoError(t, err) assert.Greater(t, id, int64(0)) assert.Equal(t, id, profile.Id) // 验证数据已保存 saved, err := FindOneProfile(ctx, db, id) require.NoError(t, err) assert.Equal(t, "http://example.com/avatar.jpg", saved.Avatar) assert.Equal(t, "Test bio", saved.Bio) } // TestFindOneProfile 测试根据ID查询个人资料 func TestFindOneProfile(t *testing.T) { db := setupProfileModelTestDB(t) _, profileId := createTestUserProfile(t, db) ctx := context.Background() // 查询个人资料 found, err := FindOneProfile(ctx, db, profileId) require.NoError(t, err) require.NotNil(t, found) assert.Equal(t, profileId, found.Id) assert.Equal(t, "http://example.com/avatar.jpg", found.Avatar) assert.Equal(t, "Test bio", found.Bio) } // TestFindOneProfile_NotFound 测试查询不存在的个人资料 func TestFindOneProfile_NotFound(t *testing.T) { db := setupProfileModelTestDB(t) ctx := context.Background() found, err := FindOneProfile(ctx, db, 99999) require.Error(t, err) require.Nil(t, found) assert.Equal(t, ErrNotFound, err) } // TestFindProfileByUserId 测试根据用户ID查询个人资料 func TestFindProfileByUserId(t *testing.T) { db := setupProfileModelTestDB(t) userId, _ := createTestUserProfile(t, db) ctx := context.Background() // 根据用户ID查询 found, err := FindProfileByUserId(ctx, db, userId) require.NoError(t, err) require.NotNil(t, found) assert.Equal(t, userId, found.UserId) assert.Equal(t, "http://example.com/avatar.jpg", found.Avatar) } // TestFindProfileByUserId_NotFound 测试查询不存在的用户个人资料 func TestFindProfileByUserId_NotFound(t *testing.T) { db := setupProfileModelTestDB(t) ctx := context.Background() found, err := FindProfileByUserId(ctx, db, 99999) require.Error(t, err) require.Nil(t, found) assert.Equal(t, ErrNotFound, err) } // TestUpdateProfile 测试更新个人资料 func TestUpdateProfile(t *testing.T) { db := setupProfileModelTestDB(t) _, profileId := createTestUserProfile(t, db) ctx := context.Background() // 获取个人资料 profile, err := FindOneProfile(ctx, db, profileId) require.NoError(t, err) // 修改数据 profile.Avatar = "http://example.com/newavatar.jpg" profile.Bio = "Updated bio" // 更新 err = UpdateProfile(ctx, db, profile) require.NoError(t, err) // 验证更新结果 updated, err := FindOneProfile(ctx, db, profileId) require.NoError(t, err) assert.Equal(t, "http://example.com/newavatar.jpg", updated.Avatar) assert.Equal(t, "Updated bio", updated.Bio) } // TestDeleteProfile 测试删除个人资料 func TestDeleteProfile(t *testing.T) { db := setupProfileModelTestDB(t) _, profileId := createTestUserProfile(t, db) ctx := context.Background() // 删除个人资料 err := DeleteProfile(ctx, db, profileId) require.NoError(t, err) // 验证个人资料已被删除 _, err = FindOneProfile(ctx, db, profileId) require.Error(t, err) assert.Equal(t, ErrNotFound, err) } // TestProfile_UserProfileRelation 测试用户与个人资料的关联 func TestProfile_UserProfileRelation(t *testing.T) { db := setupProfileModelTestDB(t) ctx := context.Background() // 创建多个用户 now := time.Now() users := []User{ {Username: "user1", Email: "user1@example.com", Password: "pass", Status: 1, CreatedAt: now, UpdatedAt: now}, {Username: "user2", Email: "user2@example.com", Password: "pass", Status: 1, CreatedAt: now, UpdatedAt: now}, {Username: "user3", Email: "user3@example.com", Password: "pass", Status: 1, CreatedAt: now, UpdatedAt: now}, } for _, u := range users { err := db.Create(&u).Error require.NoError(t, err) } // 只为 user1 和 user2 创建个人资料 profile1 := &Profile{UserId: users[0].Id, Avatar: "avatar1.jpg", Bio: "Bio 1", CreatedAt: now, UpdatedAt: now} profile2 := &Profile{UserId: users[1].Id, Avatar: "avatar2.jpg", Bio: "Bio 2", CreatedAt: now, UpdatedAt: now} err := db.Create(profile1).Error require.NoError(t, err) err = db.Create(profile2).Error require.NoError(t, err) // 验证 user1 有个人资料 found1, err := FindProfileByUserId(ctx, db, users[0].Id) require.NoError(t, err) assert.Equal(t, "avatar1.jpg", found1.Avatar) // 验证 user2 有个人资料 found2, err := FindProfileByUserId(ctx, db, users[1].Id) require.NoError(t, err) assert.Equal(t, "avatar2.jpg", found2.Avatar) // 验证 user3 没有个人资料 found3, err := FindProfileByUserId(ctx, db, users[2].Id) require.Error(t, err) require.Nil(t, found3) } // TestProfile_UniqueUserId 测试用户ID唯一性约束 func TestProfile_UniqueUserId(t *testing.T) { db := setupProfileModelTestDB(t) ctx := context.Background() // 创建用户 now := time.Now() user := &User{ Username: "testuser", Email: "test@example.com", Password: "encryptedpassword", Status: 1, CreatedAt: now, UpdatedAt: now, } err := db.Create(user).Error require.NoError(t, err) // 创建第一个个人资料 profile1 := &Profile{ UserId: user.Id, Avatar: "avatar1.jpg", Bio: "Bio 1", } id, err := InsertProfile(ctx, db, profile1) require.NoError(t, err) assert.Greater(t, id, int64(0)) // 尝试为同一用户创建第二个个人资料(应该失败) profile2 := &Profile{ UserId: user.Id, Avatar: "avatar2.jpg", Bio: "Bio 2", } _, err = InsertProfile(ctx, db, profile2) // 验证结果 - 应该返回错误(违反唯一性约束) require.Error(t, err) } // TestProfile_EmptyFields 测试空字段 func TestProfile_EmptyFields(t *testing.T) { db := setupProfileModelTestDB(t) ctx := context.Background() // 创建用户 now := time.Now() user := &User{ Username: "testuser", Email: "test@example.com", Password: "encryptedpassword", Status: 1, CreatedAt: now, UpdatedAt: now, } err := db.Create(user).Error require.NoError(t, err) // 创建空个人资料 profile := &Profile{ UserId: user.Id, Avatar: "", Bio: "", } id, err := InsertProfile(ctx, db, profile) require.NoError(t, err) assert.Greater(t, id, int64(0)) // 验证保存成功 saved, err := FindOneProfile(ctx, db, id) require.NoError(t, err) assert.Equal(t, "", saved.Avatar) assert.Equal(t, "", saved.Bio) } // BenchmarkInsertProfile 性能测试 func BenchmarkInsertProfile(b *testing.B) { db := setupProfileModelTestDB(&testing.T{}) ctx := context.Background() // 创建测试用户 now := time.Now() user := &User{ Username: "testuser", Email: "test@example.com", Password: "encryptedpassword", Status: 1, CreatedAt: now, UpdatedAt: now, } err := db.Create(user).Error if err != nil { b.Fatal(err) } b.ResetTimer() for i := 0; i < b.N; i++ { profile := &Profile{ UserId: user.Id, Avatar: "http://example.com/avatar.jpg", Bio: "Test bio", } _, _ = InsertProfile(ctx, db, profile) } } // BenchmarkFindProfileByUserId 性能测试 func BenchmarkFindProfileByUserId(b *testing.B) { db := setupProfileModelTestDB(&testing.T{}) ctx := context.Background() // 创建测试用户和个人资料 now := time.Now() user := &User{ Username: "testuser", Email: "test@example.com", Password: "encryptedpassword", Status: 1, CreatedAt: now, UpdatedAt: now, } err := db.Create(user).Error if err != nil { b.Fatal(err) } profile := &Profile{ UserId: user.Id, Avatar: "http://example.com/avatar.jpg", Bio: "Test bio", CreatedAt: now, UpdatedAt: now, } err = db.Create(profile).Error if err != nil { b.Fatal(err) } b.ResetTimer() for i := 0; i < b.N; i++ { _, _ = FindProfileByUserId(ctx, db, user.Id) } }