You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

408 lines
9.5 KiB

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)
}
}