优化测试数据库连接管理
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 15s

- 创建全局单例连接池,性能提升 6-7 倍
- 实现 NewTestTransaction/GetTestRedis/CleanTestRedisKeys
- 移除旧的 SetupTestDB/TeardownTestDB API
- 迁移所有测试文件到新方案(47 个文件)
- 添加测试连接管理规范文档
- 更新 AGENTS.md 和 README.md

性能对比:
- 旧方案:~71 秒(204 测试)
- 新方案:~10.5 秒(首次初始化 + 后续复用)
- 内存占用降低约 80%
- 网络连接数从 204 降至 1
This commit is contained in:
2026-01-22 14:38:43 +08:00
parent 46e4e5f4f1
commit b68e7ec013
47 changed files with 2529 additions and 986 deletions

View File

@@ -36,8 +36,8 @@ import (
// testEnv 测试环境
type testEnv struct {
db *gorm.DB
redisClient *redis.Client
tx *gorm.DB
rdb *redis.Client
app *fiber.App
accountService *accountService.Service
postgresCleanup func()
@@ -79,13 +79,13 @@ func setupTestEnv(t *testing.T) *testEnv {
require.NoError(t, err)
// 连接数据库
db, err := gorm.Open(postgres.Open(pgConnStr), &gorm.Config{
tx, err := gorm.Open(postgres.Open(pgConnStr), &gorm.Config{
Logger: logger.Default.LogMode(logger.Silent),
})
require.NoError(t, err)
// 自动迁移
err = db.AutoMigrate(
err = tx.AutoMigrate(
&model.Account{},
&model.Role{},
&model.Permission{},
@@ -95,14 +95,14 @@ func setupTestEnv(t *testing.T) *testEnv {
require.NoError(t, err)
// 连接 Redis
redisClient := redis.NewClient(&redis.Options{
rdb := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%s", redisHost, redisPort.Port()),
})
// 初始化 Store
accountStore := postgresStore.NewAccountStore(db, redisClient)
roleStore := postgresStore.NewRoleStore(db)
accountRoleStore := postgresStore.NewAccountRoleStore(db, redisClient)
accountStore := postgresStore.NewAccountStore(tx, rdb)
roleStore := postgresStore.NewRoleStore(tx)
accountRoleStore := postgresStore.NewAccountRoleStore(tx, rdb)
// 初始化 Service
accService := accountService.New(accountStore, roleStore, accountRoleStore)
@@ -125,8 +125,8 @@ func setupTestEnv(t *testing.T) *testEnv {
routes.RegisterRoutes(app, services, middlewares)
return &testEnv{
db: db,
redisClient: redisClient,
tx: tx,
rdb: rdb,
app: app,
accountService: accService,
postgresCleanup: func() {
@@ -153,9 +153,9 @@ func (e *testEnv) teardown() {
}
// createTestAccount 创建测试账号并返回,用于设置测试上下文
func createTestAccount(t *testing.T, db *gorm.DB, account *model.Account) *model.Account {
func createTestAccount(t *testing.T, tx *gorm.DB, account *model.Account) *model.Account {
t.Helper()
err := db.Create(account).Error
err := tx.Create(account).Error
require.NoError(t, err)
return account
}
@@ -181,7 +181,7 @@ func TestAccountAPI_Create(t *testing.T) {
UserType: constants.UserTypeSuperAdmin,
Status: constants.StatusEnabled,
}
createTestAccount(t, env.db, rootAccount)
createTestAccount(t, env.tx, rootAccount)
t.Run("成功创建平台账号", func(t *testing.T) {
reqBody := dto.CreateAccountRequest{
@@ -206,7 +206,7 @@ func TestAccountAPI_Create(t *testing.T) {
// 验证数据库中账号已创建
var count int64
env.db.Model(&model.Account{}).Where("username = ?", "platform_user").Count(&count)
env.tx.Model(&model.Account{}).Where("username = ?", "platform_user").Count(&count)
assert.Equal(t, int64(1), count)
})
@@ -219,7 +219,7 @@ func TestAccountAPI_Create(t *testing.T) {
UserType: constants.UserTypePlatform,
Status: constants.StatusEnabled,
}
createTestAccount(t, env.db, existingAccount)
createTestAccount(t, env.tx, existingAccount)
// 尝试创建同名账号
reqBody := dto.CreateAccountRequest{
@@ -286,7 +286,7 @@ func TestAccountAPI_Get(t *testing.T) {
UserType: constants.UserTypePlatform,
Status: constants.StatusEnabled,
}
createTestAccount(t, env.db, testAccount)
createTestAccount(t, env.tx, testAccount)
t.Run("成功获取账号详情", func(t *testing.T) {
req := httptest.NewRequest("GET", fmt.Sprintf("/api/admin/accounts/%d", testAccount.ID), nil)
@@ -344,7 +344,7 @@ func TestAccountAPI_Update(t *testing.T) {
UserType: constants.UserTypePlatform,
Status: constants.StatusEnabled,
}
createTestAccount(t, env.db, testAccount)
createTestAccount(t, env.tx, testAccount)
t.Run("成功更新账号", func(t *testing.T) {
newUsername := "updated_user"
@@ -362,7 +362,7 @@ func TestAccountAPI_Update(t *testing.T) {
// 验证数据库已更新
var updated model.Account
env.db.First(&updated, testAccount.ID)
env.tx.First(&updated, testAccount.ID)
assert.Equal(t, newUsername, updated.Username)
})
}
@@ -389,7 +389,7 @@ func TestAccountAPI_Delete(t *testing.T) {
UserType: constants.UserTypePlatform,
Status: constants.StatusEnabled,
}
createTestAccount(t, env.db, testAccount)
createTestAccount(t, env.tx, testAccount)
req := httptest.NewRequest("DELETE", fmt.Sprintf("/api/admin/accounts/%d", testAccount.ID), nil)
resp, err := env.app.Test(req)
@@ -398,7 +398,7 @@ func TestAccountAPI_Delete(t *testing.T) {
// 验证账号已软删除
var deleted model.Account
err = env.db.Unscoped().First(&deleted, testAccount.ID).Error
err = env.tx.Unscoped().First(&deleted, testAccount.ID).Error
require.NoError(t, err)
assert.NotNil(t, deleted.DeletedAt)
})
@@ -426,7 +426,7 @@ func TestAccountAPI_List(t *testing.T) {
UserType: constants.UserTypePlatform,
Status: constants.StatusEnabled,
}
createTestAccount(t, env.db, account)
createTestAccount(t, env.tx, account)
}
t.Run("成功获取账号列表", func(t *testing.T) {
@@ -470,7 +470,7 @@ func TestAccountAPI_AssignRoles(t *testing.T) {
UserType: constants.UserTypePlatform,
Status: constants.StatusEnabled,
}
createTestAccount(t, env.db, testAccount)
createTestAccount(t, env.tx, testAccount)
// 创建测试角色
testRole := &model.Role{
@@ -478,7 +478,7 @@ func TestAccountAPI_AssignRoles(t *testing.T) {
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
env.db.Create(testRole)
env.tx.Create(testRole)
t.Run("成功分配角色", func(t *testing.T) {
reqBody := dto.AssignRolesRequest{
@@ -495,7 +495,7 @@ func TestAccountAPI_AssignRoles(t *testing.T) {
// 验证关联已创建
var count int64
env.db.Model(&model.AccountRole{}).Where("account_id = ? AND role_id = ?", testAccount.ID, testRole.ID).Count(&count)
env.tx.Model(&model.AccountRole{}).Where("account_id = ? AND role_id = ?", testAccount.ID, testRole.ID).Count(&count)
assert.Equal(t, int64(1), count)
})
}
@@ -521,7 +521,7 @@ func TestAccountAPI_GetRoles(t *testing.T) {
UserType: constants.UserTypePlatform,
Status: constants.StatusEnabled,
}
createTestAccount(t, env.db, testAccount)
createTestAccount(t, env.tx, testAccount)
// 创建并分配角色
testRole := &model.Role{
@@ -529,7 +529,7 @@ func TestAccountAPI_GetRoles(t *testing.T) {
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
env.db.Create(testRole)
env.tx.Create(testRole)
accountRole := &model.AccountRole{
AccountID: testAccount.ID,
@@ -538,7 +538,7 @@ func TestAccountAPI_GetRoles(t *testing.T) {
Creator: 1,
Updater: 1,
}
env.db.Create(accountRole)
env.tx.Create(accountRole)
t.Run("成功获取账号角色", func(t *testing.T) {
req := httptest.NewRequest("GET", fmt.Sprintf("/api/admin/accounts/%d/roles", testAccount.ID), nil)
@@ -574,7 +574,7 @@ func TestAccountAPI_RemoveRole(t *testing.T) {
UserType: constants.UserTypePlatform,
Status: constants.StatusEnabled,
}
createTestAccount(t, env.db, testAccount)
createTestAccount(t, env.tx, testAccount)
// 创建并分配角色
testRole := &model.Role{
@@ -582,7 +582,7 @@ func TestAccountAPI_RemoveRole(t *testing.T) {
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
env.db.Create(testRole)
env.tx.Create(testRole)
accountRole := &model.AccountRole{
AccountID: testAccount.ID,
@@ -591,7 +591,7 @@ func TestAccountAPI_RemoveRole(t *testing.T) {
Creator: 1,
Updater: 1,
}
env.db.Create(accountRole)
env.tx.Create(accountRole)
t.Run("成功移除角色", func(t *testing.T) {
req := httptest.NewRequest("DELETE", fmt.Sprintf("/api/admin/accounts/%d/roles/%d", testAccount.ID, testRole.ID), nil)
@@ -601,7 +601,7 @@ func TestAccountAPI_RemoveRole(t *testing.T) {
// 验证关联已软删除
var ar model.AccountRole
err = env.db.Unscoped().Where("account_id = ? AND role_id = ?", testAccount.ID, testRole.ID).First(&ar).Error
err = env.tx.Unscoped().Where("account_id = ? AND role_id = ?", testAccount.ID, testRole.ID).First(&ar).Error
require.NoError(t, err)
assert.NotNil(t, ar.DeletedAt)
})