优化测试数据库连接管理
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

@@ -56,13 +56,13 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) {
redisPort, _ := redisContainer.MappedPort(ctx, "6379")
// 连接数据库
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.AccountRole{},
@@ -70,14 +70,14 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) {
require.NoError(t, err)
// 连接 Redis
redisClient := redis.NewClient(&redis.Options{
rdb := redis.NewClient(&redis.Options{
Addr: redisHost + ":" + redisPort.Port(),
})
// 初始化 Store 和 Service
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)
accService := accountService.New(accountStore, roleStore, accountRoleStore)
// 创建测试用户上下文
@@ -92,7 +92,7 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) {
UserType: constants.UserTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(account)
tx.Create(account)
// 创建测试角色
role := &model.Role{
@@ -100,7 +100,7 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) {
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(role)
tx.Create(role)
// 分配角色
ars, err := accService.AssignRoles(userCtx, account.ID, []uint{role.ID})
@@ -119,7 +119,7 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) {
UserType: constants.UserTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(account)
tx.Create(account)
// 创建多个测试角色
roles := make([]*model.Role, 3)
@@ -130,7 +130,7 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) {
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(roles[i])
tx.Create(roles[i])
roleIDs[i] = roles[i].ID
}
@@ -149,7 +149,7 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) {
UserType: constants.UserTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(account)
tx.Create(account)
// 创建并分配角色
role := &model.Role{
@@ -157,7 +157,7 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) {
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(role)
tx.Create(role)
_, err := accService.AssignRoles(userCtx, account.ID, []uint{role.ID})
require.NoError(t, err)
@@ -178,7 +178,7 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) {
UserType: constants.UserTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(account)
tx.Create(account)
// 创建并分配角色
role := &model.Role{
@@ -186,7 +186,7 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) {
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(role)
tx.Create(role)
_, err := accService.AssignRoles(userCtx, account.ID, []uint{role.ID})
require.NoError(t, err)
@@ -197,7 +197,7 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) {
// 验证角色已被软删除
var ar model.AccountRole
err = db.Unscoped().Where("account_id = ? AND role_id = ?", account.ID, role.ID).First(&ar).Error
err = tx.Unscoped().Where("account_id = ? AND role_id = ?", account.ID, role.ID).First(&ar).Error
require.NoError(t, err)
assert.NotNil(t, ar.DeletedAt)
})
@@ -211,7 +211,7 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) {
UserType: constants.UserTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(account)
tx.Create(account)
// 创建测试角色
role := &model.Role{
@@ -219,7 +219,7 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) {
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(role)
tx.Create(role)
// 第一次分配
_, err := accService.AssignRoles(userCtx, account.ID, []uint{role.ID})
@@ -231,7 +231,7 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) {
// 验证只有一条记录
var count int64
db.Model(&model.AccountRole{}).Where("account_id = ? AND role_id = ?", account.ID, role.ID).Count(&count)
tx.Model(&model.AccountRole{}).Where("account_id = ? AND role_id = ?", account.ID, role.ID).Count(&count)
assert.Equal(t, int64(1), count)
})
@@ -241,7 +241,7 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) {
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(role)
tx.Create(role)
_, err := accService.AssignRoles(userCtx, 99999, []uint{role.ID})
assert.Error(t, err)
@@ -255,7 +255,7 @@ func TestAccountRoleAssociation_AssignRoles(t *testing.T) {
UserType: constants.UserTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(account)
tx.Create(account)
_, err := accService.AssignRoles(userCtx, account.ID, []uint{99999})
assert.Error(t, err)
@@ -293,18 +293,18 @@ func TestAccountRoleAssociation_SoftDelete(t *testing.T) {
redisPort, _ := redisContainer.MappedPort(ctx, "6379")
// 设置环境
db, _ := gorm.Open(postgres.Open(pgConnStr), &gorm.Config{
tx, _ := gorm.Open(postgres.Open(pgConnStr), &gorm.Config{
Logger: logger.Default.LogMode(logger.Silent),
})
_ = db.AutoMigrate(&model.Account{}, &model.Role{}, &model.AccountRole{})
_ = tx.AutoMigrate(&model.Account{}, &model.Role{}, &model.AccountRole{})
redisClient := redis.NewClient(&redis.Options{
rdb := redis.NewClient(&redis.Options{
Addr: redisHost + ":" + redisPort.Port(),
})
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)
accService := accountService.New(accountStore, roleStore, accountRoleStore)
userCtx := middleware.SetUserContext(ctx, middleware.NewSimpleUserContext(1, constants.UserTypeSuperAdmin, 0))
@@ -318,14 +318,14 @@ func TestAccountRoleAssociation_SoftDelete(t *testing.T) {
UserType: constants.UserTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(account)
tx.Create(account)
role := &model.Role{
RoleName: "恢复角色测试",
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(role)
tx.Create(role)
// 分配角色
_, err := accService.AssignRoles(userCtx, account.ID, []uint{role.ID})

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

View File

@@ -33,8 +33,8 @@ import (
// regressionTestEnv 回归测试环境
type regressionTestEnv struct {
db *gorm.DB
redisClient *redis.Client
tx *gorm.DB
rdb *redis.Client
app *fiber.App
postgresCleanup func()
redisCleanup func()
@@ -75,13 +75,13 @@ func setupRegressionTestEnv(t *testing.T) *regressionTestEnv {
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{},
@@ -91,21 +91,21 @@ func setupRegressionTestEnv(t *testing.T) *regressionTestEnv {
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)
permStore := postgresStore.NewPermissionStore(db)
accountRoleStore := postgresStore.NewAccountRoleStore(db, redisClient)
rolePermStore := postgresStore.NewRolePermissionStore(db, redisClient)
accountStore := postgresStore.NewAccountStore(tx, rdb)
roleStore := postgresStore.NewRoleStore(tx)
permStore := postgresStore.NewPermissionStore(tx)
accountRoleStore := postgresStore.NewAccountRoleStore(tx, rdb)
rolePermStore := postgresStore.NewRolePermissionStore(tx, rdb)
// 初始化所有 Service
accService := accountService.New(accountStore, roleStore, accountRoleStore)
roleSvc := roleService.New(roleStore, permStore, rolePermStore)
permSvc := permissionService.New(permStore, accountRoleStore, rolePermStore, redisClient)
permSvc := permissionService.New(permStore, accountRoleStore, rolePermStore, rdb)
// 初始化所有 Handler
accountHandler := admin.NewAccountHandler(accService)
@@ -136,8 +136,8 @@ func setupRegressionTestEnv(t *testing.T) *regressionTestEnv {
routes.RegisterRoutes(app, services, middlewares)
return &regressionTestEnv{
db: db,
redisClient: redisClient,
tx: tx,
rdb: rdb,
app: app,
postgresCleanup: func() {
if err := pgContainer.Terminate(ctx); err != nil {
@@ -212,7 +212,7 @@ func TestAPIRegression_RouteModularization(t *testing.T) {
UserType: constants.UserTypePlatform,
Status: constants.StatusEnabled,
}
env.db.Create(account)
env.tx.Create(account)
// 测试获取账号
req := httptest.NewRequest("GET", fmt.Sprintf("/api/admin/accounts/%d", account.ID), nil)
@@ -234,7 +234,7 @@ func TestAPIRegression_RouteModularization(t *testing.T) {
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
env.db.Create(role)
env.tx.Create(role)
// 测试获取角色
req := httptest.NewRequest("GET", fmt.Sprintf("/api/admin/roles/%d", role.ID), nil)
@@ -257,7 +257,7 @@ func TestAPIRegression_RouteModularization(t *testing.T) {
PermType: constants.PermissionTypeMenu,
Status: constants.StatusEnabled,
}
env.db.Create(perm)
env.tx.Create(perm)
// 测试获取权限
req := httptest.NewRequest("GET", fmt.Sprintf("/api/admin/permissions/%d", perm.ID), nil)
@@ -324,7 +324,7 @@ func TestAPIRegression_Pagination(t *testing.T) {
UserType: constants.UserTypePlatform,
Status: constants.StatusEnabled,
}
env.db.Create(account)
env.tx.Create(account)
}
t.Run("分页参数正常工作", func(t *testing.T) {

View File

@@ -253,7 +253,7 @@ func TestErrorHandler_ResponseFormatConsistency(t *testing.T) {
},
{
name: "数据库错误",
path: "/api/test/db-error",
path: "/api/test/tx-error",
method: "GET",
errorCode: errors.CodeDatabaseError,
errorMsg: "数据库连接失败",
@@ -687,7 +687,7 @@ func TestErrorClassification_SensitiveInfoHidden(t *testing.T) {
}{
{
name: "数据库连接错误",
path: "/api/test/db-connection",
path: "/api/test/tx-connection",
errorCode: errors.CodeDatabaseError,
sensitiveMsg: "connection refused: tcp 192.168.1.100:5432",
expectedStatus: 500,

View File

@@ -21,7 +21,7 @@ func TestHealthCheckNormal(t *testing.T) {
logger, _ := zap.NewDevelopment()
// 初始化内存数据库
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
tx, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
require.NoError(t, err)
// 初始化 Redis 客户端(使用本地 Redis
@@ -35,7 +35,7 @@ func TestHealthCheckNormal(t *testing.T) {
app := fiber.New()
// 创建健康检查处理器
healthHandler := handler.NewHealthHandler(db, rdb, logger)
healthHandler := handler.NewHealthHandler(tx, rdb, logger)
app.Get("/health", healthHandler.Check)
// 发送测试请求
@@ -59,7 +59,7 @@ func TestHealthCheckDatabaseDown(t *testing.T) {
logger, _ := zap.NewDevelopment()
// 初始化一个会失败的数据库连接
db, err := gorm.Open(sqlite.Open("/invalid/path/test.db"), &gorm.Config{})
tx, err := gorm.Open(sqlite.Open("/invalid/path/test.tx"), &gorm.Config{})
if err != nil {
// 预期会失败
t.Log("数据库连接失败(预期行为)")
@@ -76,7 +76,7 @@ func TestHealthCheckDatabaseDown(t *testing.T) {
app := fiber.New()
// 创建健康检查处理器
healthHandler := handler.NewHealthHandler(db, rdb, logger)
healthHandler := handler.NewHealthHandler(tx, rdb, logger)
app.Get("/health", healthHandler.Check)
// 发送测试请求
@@ -95,7 +95,7 @@ func TestHealthCheckRedisDown(t *testing.T) {
logger, _ := zap.NewDevelopment()
// 初始化内存数据库
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
tx, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
require.NoError(t, err)
// 初始化一个连接到无效地址的 Redis 客户端
@@ -109,7 +109,7 @@ func TestHealthCheckRedisDown(t *testing.T) {
app := fiber.New()
// 创建健康检查处理器
healthHandler := handler.NewHealthHandler(db, rdb, logger)
healthHandler := handler.NewHealthHandler(tx, rdb, logger)
app.Get("/health", healthHandler.Check)
// 发送测试请求
@@ -128,7 +128,7 @@ func TestHealthCheckDetailed(t *testing.T) {
logger, _ := zap.NewDevelopment()
// 初始化内存数据库
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
tx, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
require.NoError(t, err)
// 初始化 Redis 客户端
@@ -149,7 +149,7 @@ func TestHealthCheckDetailed(t *testing.T) {
app := fiber.New()
// 创建健康检查处理器
healthHandler := handler.NewHealthHandler(db, rdb, logger)
healthHandler := handler.NewHealthHandler(tx, rdb, logger)
app.Get("/health", healthHandler.Check)
// 发送测试请求

View File

@@ -63,7 +63,7 @@ func TestMigration_UpAndDown(t *testing.T) {
require.NoError(t, err, "执行向上迁移失败")
// 验证表已创建
db, err := gorm.Open(postgresDriver.Open(connStr), &gorm.Config{
tx, err := gorm.Open(postgresDriver.Open(connStr), &gorm.Config{
Logger: logger.Default.LogMode(logger.Silent),
})
require.NoError(t, err, "连接数据库失败")
@@ -79,14 +79,14 @@ func TestMigration_UpAndDown(t *testing.T) {
for _, table := range tables {
var exists bool
err := db.Raw("SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = ?)", table).Scan(&exists).Error
err := tx.Raw("SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = ?)", table).Scan(&exists).Error
assert.NoError(t, err)
assert.True(t, exists, "表 %s 应该存在", table)
}
// 检查索引
var indexCount int64
err = db.Raw(`
err = tx.Raw(`
SELECT COUNT(*) FROM pg_indexes
WHERE tablename = 'tb_account'
AND indexname LIKE 'idx_account_%'
@@ -94,7 +94,7 @@ func TestMigration_UpAndDown(t *testing.T) {
assert.NoError(t, err)
assert.Greater(t, indexCount, int64(0), "tb_account 表应该有索引")
sqlDB, _ := db.DB()
sqlDB, _ := tx.DB()
if sqlDB != nil {
_ = sqlDB.Close()
}
@@ -105,7 +105,7 @@ func TestMigration_UpAndDown(t *testing.T) {
require.NoError(t, err, "执行向下迁移失败")
// 验证表已删除
db, err := gorm.Open(postgresDriver.Open(connStr), &gorm.Config{
tx, err := gorm.Open(postgresDriver.Open(connStr), &gorm.Config{
Logger: logger.Default.LogMode(logger.Silent),
})
require.NoError(t, err, "连接数据库失败")
@@ -121,12 +121,12 @@ func TestMigration_UpAndDown(t *testing.T) {
for _, table := range tables {
var exists bool
err := db.Raw("SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = ?)", table).Scan(&exists).Error
err := tx.Raw("SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = ?)", table).Scan(&exists).Error
assert.NoError(t, err)
assert.False(t, exists, "表 %s 应该已删除", table)
}
sqlDB, _ := db.DB()
sqlDB, _ := tx.DB()
if sqlDB != nil {
_ = sqlDB.Close()
}
@@ -200,12 +200,12 @@ func TestMigration_SoftDeleteSupport(t *testing.T) {
require.NoError(t, err, "执行向上迁移失败")
// 连接数据库验证
db, err := gorm.Open(postgresDriver.Open(connStr), &gorm.Config{
tx, err := gorm.Open(postgresDriver.Open(connStr), &gorm.Config{
Logger: logger.Default.LogMode(logger.Silent),
})
require.NoError(t, err, "连接数据库失败")
defer func() {
sqlDB, _ := db.DB()
sqlDB, _ := tx.DB()
if sqlDB != nil {
_ = sqlDB.Close()
}
@@ -223,7 +223,7 @@ func TestMigration_SoftDeleteSupport(t *testing.T) {
for _, table := range tables {
// 检查 deleted_at 列存在
var columnExists bool
err := db.Raw(`
err := tx.Raw(`
SELECT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = ? AND column_name = 'deleted_at'

View File

@@ -121,8 +121,9 @@ func TestPermissionMiddleware_Unauthorized(t *testing.T) {
//
// func TestPermissionMiddleware_Integration(t *testing.T) {
// // 1. 初始化数据库和 Redis
// db, redisClient := testutils.SetupTestDB(t)
// defer testutils.TeardownTestDB(t, db, redisClient)
// tx := testutils.NewTestTransaction(t)
// rdb := testutils.GetTestRedis(t)
// testutils.CleanTestRedisKeys(t, rdb)
//
// // 2. 创建测试数据(用户、角色、权限)
// // ...

View File

@@ -36,8 +36,8 @@ import (
// permTestEnv 权限测试环境
type permTestEnv struct {
db *gorm.DB
redisClient *redis.Client
tx *gorm.DB
rdb *redis.Client
app *fiber.App
permissionService *permissionService.Service
cleanup func()
@@ -78,29 +78,29 @@ func setupPermTestEnv(t *testing.T) *permTestEnv {
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.Permission{},
)
require.NoError(t, err)
// 连接 Redis
redisClient := redis.NewClient(&redis.Options{
rdb := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%s", redisHost, redisPort.Port()),
})
// 初始化 Store
permStore := postgresStore.NewPermissionStore(db)
accountRoleStore := postgresStore.NewAccountRoleStore(db, redisClient)
rolePermStore := postgresStore.NewRolePermissionStore(db, redisClient)
permStore := postgresStore.NewPermissionStore(tx)
accountRoleStore := postgresStore.NewAccountRoleStore(tx, rdb)
rolePermStore := postgresStore.NewRolePermissionStore(tx, rdb)
// 初始化 Service
permSvc := permissionService.New(permStore, accountRoleStore, rolePermStore, redisClient)
permSvc := permissionService.New(permStore, accountRoleStore, rolePermStore, rdb)
// 初始化 Handler
permHandler := admin.NewPermissionHandler(permSvc)
@@ -120,8 +120,8 @@ func setupPermTestEnv(t *testing.T) *permTestEnv {
routes.RegisterRoutes(app, services, middlewares)
return &permTestEnv{
db: db,
redisClient: redisClient,
tx: tx,
rdb: rdb,
app: app,
permissionService: permSvc,
cleanup: func() {
@@ -171,7 +171,7 @@ func TestPermissionAPI_Create(t *testing.T) {
// 验证数据库中权限已创建
var count int64
env.db.Model(&model.Permission{}).Where("perm_code = ?", "user:manage").Count(&count)
env.tx.Model(&model.Permission{}).Where("perm_code = ?", "user:manage").Count(&count)
assert.Equal(t, int64(1), count)
})
@@ -183,7 +183,7 @@ func TestPermissionAPI_Create(t *testing.T) {
PermType: constants.PermissionTypeMenu,
Status: constants.StatusEnabled,
}
env.db.Create(existingPerm)
env.tx.Create(existingPerm)
// 尝试创建相同编码的权限
reqBody := dto.CreatePermissionRequest{
@@ -213,7 +213,7 @@ func TestPermissionAPI_Create(t *testing.T) {
PermType: constants.PermissionTypeMenu,
Status: constants.StatusEnabled,
}
env.db.Create(parentPerm)
env.tx.Create(parentPerm)
// 创建子权限
reqBody := dto.CreatePermissionRequest{
@@ -233,7 +233,7 @@ func TestPermissionAPI_Create(t *testing.T) {
// 验证父权限ID已设置
var child model.Permission
env.db.Where("perm_code = ?", "system:user:list").First(&child)
env.tx.Where("perm_code = ?", "system:user:list").First(&child)
assert.NotNil(t, child.ParentID)
assert.Equal(t, parentPerm.ID, *child.ParentID)
})
@@ -259,7 +259,7 @@ func TestPermissionAPI_Get(t *testing.T) {
PermType: constants.PermissionTypeMenu,
Status: constants.StatusEnabled,
}
env.db.Create(testPerm)
env.tx.Create(testPerm)
t.Run("成功获取权限详情", func(t *testing.T) {
req := httptest.NewRequest("GET", fmt.Sprintf("/api/admin/permissions/%d", testPerm.ID), nil)
@@ -305,7 +305,7 @@ func TestPermissionAPI_Update(t *testing.T) {
PermType: constants.PermissionTypeMenu,
Status: constants.StatusEnabled,
}
env.db.Create(testPerm)
env.tx.Create(testPerm)
t.Run("成功更新权限", func(t *testing.T) {
newName := "更新后权限"
@@ -323,7 +323,7 @@ func TestPermissionAPI_Update(t *testing.T) {
// 验证数据库已更新
var updated model.Permission
env.db.First(&updated, testPerm.ID)
env.tx.First(&updated, testPerm.ID)
assert.Equal(t, newName, updated.PermName)
})
}
@@ -349,7 +349,7 @@ func TestPermissionAPI_Delete(t *testing.T) {
PermType: constants.PermissionTypeMenu,
Status: constants.StatusEnabled,
}
env.db.Create(testPerm)
env.tx.Create(testPerm)
req := httptest.NewRequest("DELETE", fmt.Sprintf("/api/admin/permissions/%d", testPerm.ID), nil)
resp, err := env.app.Test(req)
@@ -358,7 +358,7 @@ func TestPermissionAPI_Delete(t *testing.T) {
// 验证权限已软删除
var deleted model.Permission
err = env.db.Unscoped().First(&deleted, testPerm.ID).Error
err = env.tx.Unscoped().First(&deleted, testPerm.ID).Error
require.NoError(t, err)
assert.NotNil(t, deleted.DeletedAt)
})
@@ -385,7 +385,7 @@ func TestPermissionAPI_List(t *testing.T) {
PermType: constants.PermissionTypeMenu,
Status: constants.StatusEnabled,
}
env.db.Create(perm)
env.tx.Create(perm)
}
t.Run("成功获取权限列表", func(t *testing.T) {
@@ -429,7 +429,7 @@ func TestPermissionAPI_GetTree(t *testing.T) {
PermType: constants.PermissionTypeMenu,
Status: constants.StatusEnabled,
}
env.db.Create(rootPerm)
env.tx.Create(rootPerm)
// 子权限
childPerm := &model.Permission{
@@ -439,7 +439,7 @@ func TestPermissionAPI_GetTree(t *testing.T) {
ParentID: &rootPerm.ID,
Status: constants.StatusEnabled,
}
env.db.Create(childPerm)
env.tx.Create(childPerm)
// 孙子权限
grandchildPerm := &model.Permission{
@@ -449,7 +449,7 @@ func TestPermissionAPI_GetTree(t *testing.T) {
ParentID: &childPerm.ID,
Status: constants.StatusEnabled,
}
env.db.Create(grandchildPerm)
env.tx.Create(grandchildPerm)
t.Run("成功获取权限树", func(t *testing.T) {
req := httptest.NewRequest("GET", "/api/admin/permissions/tree", nil)
@@ -483,7 +483,7 @@ func TestPermissionAPI_GetTreeByRoleType(t *testing.T) {
AvailableForRoleTypes: "1",
Status: constants.StatusEnabled,
}
env.db.Create(platformPerm)
env.tx.Create(platformPerm)
customerPerm := &model.Permission{
PermName: "客户权限",
@@ -492,7 +492,7 @@ func TestPermissionAPI_GetTreeByRoleType(t *testing.T) {
AvailableForRoleTypes: "2",
Status: constants.StatusEnabled,
}
env.db.Create(customerPerm)
env.tx.Create(customerPerm)
commonPerm := &model.Permission{
PermName: "通用权限",
@@ -501,7 +501,7 @@ func TestPermissionAPI_GetTreeByRoleType(t *testing.T) {
AvailableForRoleTypes: "1,2",
Status: constants.StatusEnabled,
}
env.db.Create(commonPerm)
env.tx.Create(commonPerm)
t.Run("按角色类型过滤权限树-平台角色", func(t *testing.T) {
req := httptest.NewRequest("GET", fmt.Sprintf("/api/admin/permissions/tree?available_for_role_type=%d", constants.RoleTypePlatform), nil)
@@ -559,7 +559,7 @@ func TestPermissionAPI_FilterByAvailableForRoleTypes(t *testing.T) {
AvailableForRoleTypes: "1",
Status: constants.StatusEnabled,
}
env.db.Create(platformPerm)
env.tx.Create(platformPerm)
customerPerm := &model.Permission{
PermName: "客户专用权限",
@@ -568,7 +568,7 @@ func TestPermissionAPI_FilterByAvailableForRoleTypes(t *testing.T) {
AvailableForRoleTypes: "2",
Status: constants.StatusEnabled,
}
env.db.Create(customerPerm)
env.tx.Create(customerPerm)
commonPerm := &model.Permission{
PermName: "通用权限",
@@ -577,7 +577,7 @@ func TestPermissionAPI_FilterByAvailableForRoleTypes(t *testing.T) {
AvailableForRoleTypes: "1,2",
Status: constants.StatusEnabled,
}
env.db.Create(commonPerm)
env.tx.Create(commonPerm)
t.Run("过滤平台角色可用权限", func(t *testing.T) {
req := httptest.NewRequest("GET", "/api/admin/permissions?available_for_role_type=1", nil)

View File

@@ -26,12 +26,13 @@ import (
)
func TestPlatformAccountAPI_ListPlatformAccounts(t *testing.T) {
db, redisClient := testutils.SetupTestDB(t)
defer testutils.TeardownTestDB(t, db, redisClient)
tx := testutils.NewTestTransaction(t)
rdb := testutils.GetTestRedis(t)
testutils.CleanTestRedisKeys(t, rdb)
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)
accService := accountService.New(accountStore, roleStore, accountRoleStore)
accountHandler := admin.NewAccountHandler(accService)
@@ -57,7 +58,7 @@ func TestPlatformAccountAPI_ListPlatformAccounts(t *testing.T) {
UserType: constants.UserTypeSuperAdmin,
Status: constants.StatusEnabled,
}
db.Create(superAdmin)
tx.Create(superAdmin)
platformUser := &model.Account{
Username: testutils.GenerateUsername("platform_user", 2),
@@ -66,7 +67,7 @@ func TestPlatformAccountAPI_ListPlatformAccounts(t *testing.T) {
UserType: constants.UserTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(platformUser)
tx.Create(platformUser)
agentUser := &model.Account{
Username: testutils.GenerateUsername("agent_user", 3),
@@ -75,7 +76,7 @@ func TestPlatformAccountAPI_ListPlatformAccounts(t *testing.T) {
UserType: constants.UserTypeAgent,
Status: constants.StatusEnabled,
}
db.Create(agentUser)
tx.Create(agentUser)
t.Run("列表只返回平台账号和超级管理员", func(t *testing.T) {
req := httptest.NewRequest("GET", "/api/admin/platform-accounts?page=1&page_size=20", nil)
@@ -93,7 +94,7 @@ func TestPlatformAccountAPI_ListPlatformAccounts(t *testing.T) {
assert.GreaterOrEqual(t, len(items), 2)
var count int64
db.Model(&model.Account{}).Where("user_type IN ?", []int{1, 2}).Count(&count)
tx.Model(&model.Account{}).Where("user_type IN ?", []int{1, 2}).Count(&count)
assert.GreaterOrEqual(t, count, int64(2))
})
@@ -114,12 +115,13 @@ func TestPlatformAccountAPI_ListPlatformAccounts(t *testing.T) {
}
func TestPlatformAccountAPI_UpdatePassword(t *testing.T) {
db, redisClient := testutils.SetupTestDB(t)
defer testutils.TeardownTestDB(t, db, redisClient)
tx := testutils.NewTestTransaction(t)
rdb := testutils.GetTestRedis(t)
testutils.CleanTestRedisKeys(t, rdb)
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)
accService := accountService.New(accountStore, roleStore, accountRoleStore)
accountHandler := admin.NewAccountHandler(accService)
@@ -145,7 +147,7 @@ func TestPlatformAccountAPI_UpdatePassword(t *testing.T) {
UserType: constants.UserTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(testAccount)
tx.Create(testAccount)
t.Run("成功修改密码", func(t *testing.T) {
reqBody := dto.UpdatePasswordRequest{
@@ -165,7 +167,7 @@ func TestPlatformAccountAPI_UpdatePassword(t *testing.T) {
assert.Equal(t, 0, result.Code)
var updated model.Account
db.First(&updated, testAccount.ID)
tx.First(&updated, testAccount.ID)
assert.NotEqual(t, "old_hashed_password", updated.Password)
})
@@ -188,12 +190,13 @@ func TestPlatformAccountAPI_UpdatePassword(t *testing.T) {
}
func TestPlatformAccountAPI_UpdateStatus(t *testing.T) {
db, redisClient := testutils.SetupTestDB(t)
defer testutils.TeardownTestDB(t, db, redisClient)
tx := testutils.NewTestTransaction(t)
rdb := testutils.GetTestRedis(t)
testutils.CleanTestRedisKeys(t, rdb)
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)
accService := accountService.New(accountStore, roleStore, accountRoleStore)
accountHandler := admin.NewAccountHandler(accService)
@@ -219,7 +222,7 @@ func TestPlatformAccountAPI_UpdateStatus(t *testing.T) {
UserType: constants.UserTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(testAccount)
tx.Create(testAccount)
t.Run("成功禁用账号", func(t *testing.T) {
reqBody := dto.UpdateStatusRequest{
@@ -234,7 +237,7 @@ func TestPlatformAccountAPI_UpdateStatus(t *testing.T) {
assert.Equal(t, fiber.StatusOK, resp.StatusCode)
var updated model.Account
db.First(&updated, testAccount.ID)
tx.First(&updated, testAccount.ID)
assert.Equal(t, constants.StatusDisabled, updated.Status)
})
@@ -251,18 +254,19 @@ func TestPlatformAccountAPI_UpdateStatus(t *testing.T) {
assert.Equal(t, fiber.StatusOK, resp.StatusCode)
var updated model.Account
db.First(&updated, testAccount.ID)
tx.First(&updated, testAccount.ID)
assert.Equal(t, constants.StatusEnabled, updated.Status)
})
}
func TestPlatformAccountAPI_AssignRoles(t *testing.T) {
db, redisClient := testutils.SetupTestDB(t)
defer testutils.TeardownTestDB(t, db, redisClient)
tx := testutils.NewTestTransaction(t)
rdb := testutils.GetTestRedis(t)
testutils.CleanTestRedisKeys(t, rdb)
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)
accService := accountService.New(accountStore, roleStore, accountRoleStore)
accountHandler := admin.NewAccountHandler(accService)
@@ -288,7 +292,7 @@ func TestPlatformAccountAPI_AssignRoles(t *testing.T) {
UserType: constants.UserTypeSuperAdmin,
Status: constants.StatusEnabled,
}
db.Create(superAdmin)
tx.Create(superAdmin)
platformUser := &model.Account{
Username: testutils.GenerateUsername("platform_user_role", 31),
@@ -297,14 +301,14 @@ func TestPlatformAccountAPI_AssignRoles(t *testing.T) {
UserType: constants.UserTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(platformUser)
tx.Create(platformUser)
testRole := &model.Role{
RoleName: testutils.GenerateUsername("测试角色", 30),
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(testRole)
tx.Create(testRole)
t.Run("超级管理员禁止分配角色", func(t *testing.T) {
reqBody := dto.AssignRolesRequest{
@@ -337,7 +341,7 @@ func TestPlatformAccountAPI_AssignRoles(t *testing.T) {
assert.Equal(t, fiber.StatusOK, resp.StatusCode)
var count int64
db.Model(&model.AccountRole{}).Where("account_id = ? AND role_id = ?", platformUser.ID, testRole.ID).Count(&count)
tx.Model(&model.AccountRole{}).Where("account_id = ? AND role_id = ?", platformUser.ID, testRole.ID).Count(&count)
assert.Equal(t, int64(1), count)
})
@@ -354,7 +358,7 @@ func TestPlatformAccountAPI_AssignRoles(t *testing.T) {
assert.Equal(t, fiber.StatusOK, resp.StatusCode)
var count int64
db.Model(&model.AccountRole{}).Where("account_id = ?", platformUser.ID).Count(&count)
tx.Model(&model.AccountRole{}).Where("account_id = ?", platformUser.ID).Count(&count)
assert.Equal(t, int64(0), count)
})
}

View File

@@ -54,25 +54,25 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) {
redisPort, err := redisContainer.MappedPort(ctx, "6379")
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.Role{},
&model.Permission{},
&model.RolePermission{},
)
require.NoError(t, err)
redisClient := redis.NewClient(&redis.Options{
rdb := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%s", redisHost, redisPort.Port()),
})
roleStore := postgresStore.NewRoleStore(db)
permStore := postgresStore.NewPermissionStore(db)
rolePermStore := postgresStore.NewRolePermissionStore(db, redisClient)
roleStore := postgresStore.NewRoleStore(tx)
permStore := postgresStore.NewPermissionStore(tx)
rolePermStore := postgresStore.NewRolePermissionStore(tx, rdb)
roleSvc := roleService.New(roleStore, permStore, rolePermStore)
// 创建测试用户上下文
@@ -85,7 +85,7 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) {
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(role)
tx.Create(role)
// 创建测试权限
perm := &model.Permission{
@@ -94,7 +94,7 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) {
PermType: constants.PermissionTypeMenu,
Status: constants.StatusEnabled,
}
db.Create(perm)
tx.Create(perm)
// 分配权限
rps, err := roleSvc.AssignPermissions(userCtx, role.ID, []uint{perm.ID})
@@ -111,7 +111,7 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) {
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(role)
tx.Create(role)
// 创建多个测试权限
permIDs := make([]uint, 3)
@@ -122,7 +122,7 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) {
PermType: constants.PermissionTypeMenu,
Status: constants.StatusEnabled,
}
db.Create(perm)
tx.Create(perm)
permIDs[i] = perm.ID
}
@@ -139,7 +139,7 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) {
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(role)
tx.Create(role)
// 创建并分配权限
perm := &model.Permission{
@@ -148,7 +148,7 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) {
PermType: constants.PermissionTypeMenu,
Status: constants.StatusEnabled,
}
db.Create(perm)
tx.Create(perm)
_, err := roleSvc.AssignPermissions(userCtx, role.ID, []uint{perm.ID})
require.NoError(t, err)
@@ -167,7 +167,7 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) {
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(role)
tx.Create(role)
// 创建并分配权限
perm := &model.Permission{
@@ -176,7 +176,7 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) {
PermType: constants.PermissionTypeMenu,
Status: constants.StatusEnabled,
}
db.Create(perm)
tx.Create(perm)
_, err := roleSvc.AssignPermissions(userCtx, role.ID, []uint{perm.ID})
require.NoError(t, err)
@@ -187,7 +187,7 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) {
// 验证权限已被软删除
var rp model.RolePermission
err = db.Unscoped().Where("role_id = ? AND perm_id = ?", role.ID, perm.ID).First(&rp).Error
err = tx.Unscoped().Where("role_id = ? AND perm_id = ?", role.ID, perm.ID).First(&rp).Error
require.NoError(t, err)
assert.NotNil(t, rp.DeletedAt)
})
@@ -199,7 +199,7 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) {
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(role)
tx.Create(role)
// 创建测试权限
perm := &model.Permission{
@@ -208,7 +208,7 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) {
PermType: constants.PermissionTypeMenu,
Status: constants.StatusEnabled,
}
db.Create(perm)
tx.Create(perm)
// 第一次分配
_, err := roleSvc.AssignPermissions(userCtx, role.ID, []uint{perm.ID})
@@ -220,7 +220,7 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) {
// 验证只有一条记录
var count int64
db.Model(&model.RolePermission{}).Where("role_id = ? AND perm_id = ?", role.ID, perm.ID).Count(&count)
tx.Model(&model.RolePermission{}).Where("role_id = ? AND perm_id = ?", role.ID, perm.ID).Count(&count)
assert.Equal(t, int64(1), count)
})
@@ -231,7 +231,7 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) {
PermType: constants.PermissionTypeMenu,
Status: constants.StatusEnabled,
}
db.Create(perm)
tx.Create(perm)
_, err := roleSvc.AssignPermissions(userCtx, 99999, []uint{perm.ID})
assert.Error(t, err)
@@ -243,7 +243,7 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) {
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(role)
tx.Create(role)
_, err := roleSvc.AssignPermissions(userCtx, role.ID, []uint{99999})
assert.Error(t, err)
@@ -277,18 +277,18 @@ func TestRolePermissionAssociation_SoftDelete(t *testing.T) {
redisHost, _ := redisContainer.Host(ctx)
redisPort, _ := redisContainer.MappedPort(ctx, "6379")
db, _ := gorm.Open(postgres.Open(pgConnStr), &gorm.Config{
tx, _ := gorm.Open(postgres.Open(pgConnStr), &gorm.Config{
Logger: logger.Default.LogMode(logger.Silent),
})
_ = db.AutoMigrate(&model.Role{}, &model.Permission{}, &model.RolePermission{})
_ = tx.AutoMigrate(&model.Role{}, &model.Permission{}, &model.RolePermission{})
redisClient := redis.NewClient(&redis.Options{
rdb := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%s", redisHost, redisPort.Port()),
})
roleStore := postgresStore.NewRoleStore(db)
permStore := postgresStore.NewPermissionStore(db)
rolePermStore := postgresStore.NewRolePermissionStore(db, redisClient)
roleStore := postgresStore.NewRoleStore(tx)
permStore := postgresStore.NewPermissionStore(tx)
rolePermStore := postgresStore.NewRolePermissionStore(tx, rdb)
roleSvc := roleService.New(roleStore, permStore, rolePermStore)
userCtx := middleware.SetUserContext(ctx, middleware.NewSimpleUserContext(1, constants.UserTypeSuperAdmin, 0))
@@ -300,7 +300,7 @@ func TestRolePermissionAssociation_SoftDelete(t *testing.T) {
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(role)
tx.Create(role)
perm := &model.Permission{
PermName: "恢复权限测试",
@@ -308,7 +308,7 @@ func TestRolePermissionAssociation_SoftDelete(t *testing.T) {
PermType: constants.PermissionTypeMenu,
Status: constants.StatusEnabled,
}
db.Create(perm)
tx.Create(perm)
// 分配权限
_, err := roleSvc.AssignPermissions(userCtx, role.ID, []uint{perm.ID})
@@ -336,7 +336,7 @@ func TestRolePermissionAssociation_SoftDelete(t *testing.T) {
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(role)
tx.Create(role)
// 创建多个权限
permIDs := make([]uint, 5)
@@ -347,7 +347,7 @@ func TestRolePermissionAssociation_SoftDelete(t *testing.T) {
PermType: constants.PermissionTypeMenu,
Status: constants.StatusEnabled,
}
db.Create(perm)
tx.Create(perm)
permIDs[i] = perm.ID
}
@@ -395,10 +395,10 @@ func TestRolePermissionAssociation_Cascade(t *testing.T) {
pgConnStr, _ := pgContainer.ConnectionString(ctx, "sslmode=disable")
// 设置环境
db, _ := gorm.Open(postgres.Open(pgConnStr), &gorm.Config{
tx, _ := gorm.Open(postgres.Open(pgConnStr), &gorm.Config{
Logger: logger.Default.LogMode(logger.Silent),
})
_ = db.AutoMigrate(&model.Role{}, &model.Permission{}, &model.RolePermission{})
_ = tx.AutoMigrate(&model.Role{}, &model.Permission{}, &model.RolePermission{})
t.Run("验证无外键约束(关联表独立)", func(t *testing.T) {
// 创建角色和权限
@@ -407,7 +407,7 @@ func TestRolePermissionAssociation_Cascade(t *testing.T) {
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
db.Create(role)
tx.Create(role)
perm := &model.Permission{
PermName: "级联测试权限",
@@ -415,7 +415,7 @@ func TestRolePermissionAssociation_Cascade(t *testing.T) {
PermType: constants.PermissionTypeMenu,
Status: constants.StatusEnabled,
}
db.Create(perm)
tx.Create(perm)
// 创建关联
rp := &model.RolePermission{
@@ -423,19 +423,19 @@ func TestRolePermissionAssociation_Cascade(t *testing.T) {
PermID: perm.ID,
Status: constants.StatusEnabled,
}
db.Create(rp)
tx.Create(rp)
// 删除角色(软删除)
db.Delete(role)
tx.Delete(role)
// 验证关联记录仍然存在(无外键约束)
var count int64
db.Model(&model.RolePermission{}).Where("role_id = ?", role.ID).Count(&count)
tx.Model(&model.RolePermission{}).Where("role_id = ?", role.ID).Count(&count)
assert.Equal(t, int64(1), count, "关联记录应该仍然存在,因为没有外键约束")
// 验证可以独立查询关联记录
var rpRecord model.RolePermission
err := db.Where("role_id = ? AND perm_id = ?", role.ID, perm.ID).First(&rpRecord).Error
err := tx.Where("role_id = ? AND perm_id = ?", role.ID, perm.ID).First(&rpRecord).Error
assert.NoError(t, err, "应该能查询到关联记录")
})
}

View File

@@ -36,8 +36,8 @@ import (
// roleTestEnv 角色测试环境
type roleTestEnv struct {
db *gorm.DB
redisClient *redis.Client
tx *gorm.DB
rdb *redis.Client
app *fiber.App
roleService *roleService.Service
postgresCleanup func()
@@ -79,13 +79,13 @@ func setupRoleTestEnv(t *testing.T) *roleTestEnv {
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 setupRoleTestEnv(t *testing.T) *roleTestEnv {
require.NoError(t, err)
// 连接 Redis
redisClient := redis.NewClient(&redis.Options{
rdb := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%s", redisHost, redisPort.Port()),
})
// 初始化 Store
roleStore := postgresStore.NewRoleStore(db)
permissionStore := postgresStore.NewPermissionStore(db)
rolePermissionStore := postgresStore.NewRolePermissionStore(db, redisClient)
roleStore := postgresStore.NewRoleStore(tx)
permissionStore := postgresStore.NewPermissionStore(tx)
rolePermissionStore := postgresStore.NewRolePermissionStore(tx, rdb)
// 初始化 Service
roleSvc := roleService.New(roleStore, permissionStore, rolePermissionStore)
@@ -125,8 +125,8 @@ func setupRoleTestEnv(t *testing.T) *roleTestEnv {
routes.RegisterRoutes(app, services, middlewares)
return &roleTestEnv{
db: db,
redisClient: redisClient,
tx: tx,
rdb: rdb,
app: app,
roleService: roleSvc,
postgresCleanup: func() {
@@ -187,7 +187,7 @@ func TestRoleAPI_Create(t *testing.T) {
// 验证数据库中角色已创建
var count int64
env.db.Model(&model.Role{}).Where("role_name = ?", "测试角色").Count(&count)
env.tx.Model(&model.Role{}).Where("role_name = ?", "测试角色").Count(&count)
assert.Equal(t, int64(1), count)
})
@@ -229,7 +229,7 @@ func TestRoleAPI_Get(t *testing.T) {
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
env.db.Create(testRole)
env.tx.Create(testRole)
t.Run("成功获取角色详情", func(t *testing.T) {
req := httptest.NewRequest("GET", fmt.Sprintf("/api/admin/roles/%d", testRole.ID), nil)
@@ -274,7 +274,7 @@ func TestRoleAPI_Update(t *testing.T) {
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
env.db.Create(testRole)
env.tx.Create(testRole)
t.Run("成功更新角色", func(t *testing.T) {
newName := "更新后角色"
@@ -292,7 +292,7 @@ func TestRoleAPI_Update(t *testing.T) {
// 验证数据库已更新
var updated model.Role
env.db.First(&updated, testRole.ID)
env.tx.First(&updated, testRole.ID)
assert.Equal(t, newName, updated.RoleName)
})
}
@@ -317,7 +317,7 @@ func TestRoleAPI_Delete(t *testing.T) {
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
env.db.Create(testRole)
env.tx.Create(testRole)
req := httptest.NewRequest("DELETE", fmt.Sprintf("/api/admin/roles/%d", testRole.ID), nil)
resp, err := env.app.Test(req)
@@ -326,7 +326,7 @@ func TestRoleAPI_Delete(t *testing.T) {
// 验证角色已软删除
var deleted model.Role
err = env.db.Unscoped().First(&deleted, testRole.ID).Error
err = env.tx.Unscoped().First(&deleted, testRole.ID).Error
require.NoError(t, err)
assert.NotNil(t, deleted.DeletedAt)
})
@@ -352,7 +352,7 @@ func TestRoleAPI_List(t *testing.T) {
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
env.db.Create(role)
env.tx.Create(role)
}
t.Run("成功获取角色列表", func(t *testing.T) {
@@ -387,7 +387,7 @@ func TestRoleAPI_AssignPermissions(t *testing.T) {
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
env.db.Create(testRole)
env.tx.Create(testRole)
// 创建测试权限
testPerm := &model.Permission{
@@ -396,7 +396,7 @@ func TestRoleAPI_AssignPermissions(t *testing.T) {
PermType: constants.PermissionTypeMenu,
Status: constants.StatusEnabled,
}
env.db.Create(testPerm)
env.tx.Create(testPerm)
t.Run("成功分配权限", func(t *testing.T) {
reqBody := dto.AssignPermissionsRequest{
@@ -413,7 +413,7 @@ func TestRoleAPI_AssignPermissions(t *testing.T) {
// 验证关联已创建
var count int64
env.db.Model(&model.RolePermission{}).Where("role_id = ? AND perm_id = ?", testRole.ID, testPerm.ID).Count(&count)
env.tx.Model(&model.RolePermission{}).Where("role_id = ? AND perm_id = ?", testRole.ID, testPerm.ID).Count(&count)
assert.Equal(t, int64(1), count)
})
}
@@ -437,7 +437,7 @@ func TestRoleAPI_GetPermissions(t *testing.T) {
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
env.db.Create(testRole)
env.tx.Create(testRole)
// 创建并分配权限
testPerm := &model.Permission{
@@ -446,14 +446,14 @@ func TestRoleAPI_GetPermissions(t *testing.T) {
PermType: constants.PermissionTypeMenu,
Status: constants.StatusEnabled,
}
env.db.Create(testPerm)
env.tx.Create(testPerm)
rolePerm := &model.RolePermission{
RoleID: testRole.ID,
PermID: testPerm.ID,
Status: constants.StatusEnabled,
}
env.db.Create(rolePerm)
env.tx.Create(rolePerm)
t.Run("成功获取角色权限", func(t *testing.T) {
req := httptest.NewRequest("GET", fmt.Sprintf("/api/admin/roles/%d/permissions", testRole.ID), nil)
@@ -487,7 +487,7 @@ func TestRoleAPI_RemovePermission(t *testing.T) {
RoleType: constants.RoleTypePlatform,
Status: constants.StatusEnabled,
}
env.db.Create(testRole)
env.tx.Create(testRole)
// 创建并分配权限
testPerm := &model.Permission{
@@ -496,14 +496,14 @@ func TestRoleAPI_RemovePermission(t *testing.T) {
PermType: constants.PermissionTypeMenu,
Status: constants.StatusEnabled,
}
env.db.Create(testPerm)
env.tx.Create(testPerm)
rolePerm := &model.RolePermission{
RoleID: testRole.ID,
PermID: testPerm.ID,
Status: constants.StatusEnabled,
}
env.db.Create(rolePerm)
env.tx.Create(rolePerm)
t.Run("成功移除权限", func(t *testing.T) {
req := httptest.NewRequest("DELETE", fmt.Sprintf("/api/admin/roles/%d/permissions/%d", testRole.ID, testPerm.ID), nil)
@@ -513,7 +513,7 @@ func TestRoleAPI_RemovePermission(t *testing.T) {
// 验证关联已软删除
var rp model.RolePermission
err = env.db.Unscoped().Where("role_id = ? AND perm_id = ?", testRole.ID, testPerm.ID).First(&rp).Error
err = env.tx.Unscoped().Where("role_id = ? AND perm_id = ?", testRole.ID, testPerm.ID).First(&rp).Error
require.NoError(t, err)
assert.NotNil(t, rp.DeletedAt)
})
@@ -538,7 +538,7 @@ func TestRoleAPI_UpdateStatus(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.UpdateRoleStatusRequest{
@@ -560,7 +560,7 @@ func TestRoleAPI_UpdateStatus(t *testing.T) {
// 验证数据库中状态已更新
var updated model.Role
env.db.First(&updated, testRole.ID)
env.tx.First(&updated, testRole.ID)
assert.Equal(t, constants.StatusDisabled, updated.Status)
})
@@ -584,7 +584,7 @@ func TestRoleAPI_UpdateStatus(t *testing.T) {
// 验证数据库中状态已更新
var updated model.Role
env.db.First(&updated, testRole.ID)
env.tx.First(&updated, testRole.ID)
assert.Equal(t, constants.StatusEnabled, updated.Status)
})

View File

@@ -31,8 +31,8 @@ import (
// shopAccountTestEnv 商户账号测试环境
type shopAccountTestEnv struct {
db *gorm.DB
redisClient *redis.Client
tx *gorm.DB
rdb *redis.Client
tokenManager *auth.TokenManager
app *fiber.App
adminToken string
@@ -55,12 +55,12 @@ func setupShopAccountTestEnv(t *testing.T) *shopAccountTestEnv {
zapLogger, _ := zap.NewDevelopment()
dsn := "host=cxd.whcxd.cn port=16159 user=erp_pgsql password=erp_2025 dbname=junhong_cmp_test sslmode=disable TimeZone=Asia/Shanghai"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
tx, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
Logger: logger.Default.LogMode(logger.Silent),
})
require.NoError(t, err)
err = db.AutoMigrate(
err = tx.AutoMigrate(
&model.Account{},
&model.Role{},
&model.Permission{},
@@ -72,32 +72,32 @@ func setupShopAccountTestEnv(t *testing.T) *shopAccountTestEnv {
)
require.NoError(t, err)
redisClient := redis.NewClient(&redis.Options{
rdb := redis.NewClient(&redis.Options{
Addr: "cxd.whcxd.cn:16299",
Password: "cpNbWtAaqgo1YJmbMp3h",
DB: 15,
})
ctx := context.Background()
err = redisClient.Ping(ctx).Err()
err = rdb.Ping(ctx).Err()
require.NoError(t, err)
testPrefix := fmt.Sprintf("test:%s:", t.Name())
keys, _ := redisClient.Keys(ctx, testPrefix+"*").Result()
keys, _ := rdb.Keys(ctx, testPrefix+"*").Result()
if len(keys) > 0 {
redisClient.Del(ctx, keys...)
rdb.Del(ctx, keys...)
}
tokenManager := auth.NewTokenManager(redisClient, 24*time.Hour, 7*24*time.Hour)
tokenManager := auth.NewTokenManager(rdb, 24*time.Hour, 7*24*time.Hour)
superAdmin := testutil.CreateSuperAdmin(t, db)
adminToken, _ := testutil.GenerateTestToken(t, redisClient, superAdmin, "web")
superAdmin := testutil.CreateSuperAdmin(t, tx)
adminToken, _ := testutil.GenerateTestToken(t, rdb, superAdmin, "web")
testShop := testutil.CreateTestShop(t, db, "测试商户", "TEST_SHOP", 1, nil)
testShop := testutil.CreateTestShop(t, tx, "测试商户", "TEST_SHOP", 1, nil)
deps := &bootstrap.Dependencies{
DB: db,
Redis: redisClient,
DB: tx,
Redis: rdb,
Logger: zapLogger,
TokenManager: tokenManager,
}
@@ -117,8 +117,8 @@ func setupShopAccountTestEnv(t *testing.T) *shopAccountTestEnv {
routes.RegisterRoutes(app, handlers, middlewares)
return &shopAccountTestEnv{
db: db,
redisClient: redisClient,
tx: tx,
rdb: rdb,
tokenManager: tokenManager,
app: app,
adminToken: adminToken,
@@ -130,17 +130,17 @@ func setupShopAccountTestEnv(t *testing.T) *shopAccountTestEnv {
// teardown 清理测试环境
func (e *shopAccountTestEnv) teardown() {
e.db.Exec("DELETE FROM tb_account WHERE username LIKE 'test%'")
e.db.Exec("DELETE FROM tb_shop WHERE shop_code LIKE 'TEST%'")
e.tx.Exec("DELETE FROM tb_account WHERE username LIKE 'test%'")
e.tx.Exec("DELETE FROM tb_shop WHERE shop_code LIKE 'TEST%'")
ctx := context.Background()
testPrefix := fmt.Sprintf("test:%s:", e.t.Name())
keys, _ := e.redisClient.Keys(ctx, testPrefix+"*").Result()
keys, _ := e.rdb.Keys(ctx, testPrefix+"*").Result()
if len(keys) > 0 {
e.redisClient.Del(ctx, keys...)
e.rdb.Del(ctx, keys...)
}
e.redisClient.Close()
e.rdb.Close()
}
// TestShopAccount_CreateAccount 测试创建商户账号
@@ -177,7 +177,7 @@ func TestShopAccount_CreateAccount(t *testing.T) {
// 验证数据库中的账号
var account model.Account
err = env.db.Where("username = ?", "agent001").First(&account).Error
err = env.tx.Where("username = ?", "agent001").First(&account).Error
require.NoError(t, err)
assert.Equal(t, constants.UserTypeAgent, account.UserType)
assert.NotNil(t, account.ShopID)
@@ -225,9 +225,9 @@ func TestShopAccount_ListAccounts(t *testing.T) {
defer env.teardown()
// 创建测试账号
testutil.CreateAgentUser(t, env.db, env.testShop.ID)
testutil.CreateTestAccount(t, env.db, "agent2", "pass123", constants.UserTypeAgent, &env.testShop.ID, nil)
testutil.CreateTestAccount(t, env.db, "agent3", "pass123", constants.UserTypeAgent, &env.testShop.ID, nil)
testutil.CreateAgentUser(t, env.tx, env.testShop.ID)
testutil.CreateTestAccount(t, env.tx, "agent2", "pass123", constants.UserTypeAgent, &env.testShop.ID, nil)
testutil.CreateTestAccount(t, env.tx, "agent3", "pass123", constants.UserTypeAgent, &env.testShop.ID, nil)
// 查询该商户的所有账号
req := httptest.NewRequest("GET", fmt.Sprintf("/api/admin/shop-accounts?shop_id=%d&page=1&size=10", env.testShop.ID), nil)
@@ -260,7 +260,7 @@ func TestShopAccount_UpdateAccount(t *testing.T) {
defer env.teardown()
// 创建测试账号
account := testutil.CreateAgentUser(t, env.db, env.testShop.ID)
account := testutil.CreateAgentUser(t, env.tx, env.testShop.ID)
// 更新账号用户名
reqBody := dto.UpdateShopAccountRequest{
@@ -288,7 +288,7 @@ func TestShopAccount_UpdateAccount(t *testing.T) {
// 验证数据库中的更新
var updatedAccount model.Account
err = env.db.First(&updatedAccount, account.ID).Error
err = env.tx.First(&updatedAccount, account.ID).Error
require.NoError(t, err)
assert.Equal(t, "updated_agent", updatedAccount.Username)
assert.Equal(t, account.Phone, updatedAccount.Phone) // 手机号不应该改变
@@ -300,7 +300,7 @@ func TestShopAccount_UpdatePassword(t *testing.T) {
defer env.teardown()
// 创建测试账号
account := testutil.CreateAgentUser(t, env.db, env.testShop.ID)
account := testutil.CreateAgentUser(t, env.tx, env.testShop.ID)
// 重置密码
newPassword := "newpassword456"
@@ -329,7 +329,7 @@ func TestShopAccount_UpdatePassword(t *testing.T) {
// 验证新密码
var updatedAccount model.Account
err = env.db.First(&updatedAccount, account.ID).Error
err = env.tx.First(&updatedAccount, account.ID).Error
require.NoError(t, err)
err = bcrypt.CompareHashAndPassword([]byte(updatedAccount.Password), []byte(newPassword))
@@ -346,7 +346,7 @@ func TestShopAccount_UpdateStatus(t *testing.T) {
defer env.teardown()
// 创建测试账号(默认启用)
account := testutil.CreateAgentUser(t, env.db, env.testShop.ID)
account := testutil.CreateAgentUser(t, env.tx, env.testShop.ID)
require.Equal(t, 1, account.Status)
// 禁用账号
@@ -375,7 +375,7 @@ func TestShopAccount_UpdateStatus(t *testing.T) {
// 验证账号已禁用
var disabledAccount model.Account
err = env.db.First(&disabledAccount, account.ID).Error
err = env.tx.First(&disabledAccount, account.ID).Error
require.NoError(t, err)
assert.Equal(t, 2, disabledAccount.Status)
@@ -396,7 +396,7 @@ func TestShopAccount_UpdateStatus(t *testing.T) {
// 验证账号已启用
var enabledAccount model.Account
err = env.db.First(&enabledAccount, account.ID).Error
err = env.tx.First(&enabledAccount, account.ID).Error
require.NoError(t, err)
assert.Equal(t, 1, enabledAccount.Status)
}
@@ -407,10 +407,10 @@ func TestShopAccount_DeleteShopDisablesAccounts(t *testing.T) {
defer env.teardown()
// 创建商户和多个账号
shop := testutil.CreateTestShop(t, env.db, "待删除商户", "DEL_SHOP", 1, nil)
account1 := testutil.CreateTestAccount(t, env.db, "agent1", "pass123", constants.UserTypeAgent, &shop.ID, nil)
account2 := testutil.CreateTestAccount(t, env.db, "agent2", "pass123", constants.UserTypeAgent, &shop.ID, nil)
account3 := testutil.CreateTestAccount(t, env.db, "agent3", "pass123", constants.UserTypeAgent, &shop.ID, nil)
shop := testutil.CreateTestShop(t, env.tx, "待删除商户", "DEL_SHOP", 1, nil)
account1 := testutil.CreateTestAccount(t, env.tx, "agent1", "pass123", constants.UserTypeAgent, &shop.ID, nil)
account2 := testutil.CreateTestAccount(t, env.tx, "agent2", "pass123", constants.UserTypeAgent, &shop.ID, nil)
account3 := testutil.CreateTestAccount(t, env.tx, "agent3", "pass123", constants.UserTypeAgent, &shop.ID, nil)
// 删除商户
req := httptest.NewRequest("DELETE", fmt.Sprintf("/api/admin/shops/%d", shop.ID), nil)
@@ -426,14 +426,14 @@ func TestShopAccount_DeleteShopDisablesAccounts(t *testing.T) {
accounts := []*model.Account{account1, account2, account3}
for _, acc := range accounts {
var disabledAccount model.Account
err = env.db.First(&disabledAccount, acc.ID).Error
err = env.tx.First(&disabledAccount, acc.ID).Error
require.NoError(t, err)
assert.Equal(t, 2, disabledAccount.Status, "账号 %s 应该被禁用", acc.Username)
}
// 验证商户已软删除
var deletedShop model.Shop
err = env.db.Unscoped().First(&deletedShop, shop.ID).Error
err = env.tx.Unscoped().First(&deletedShop, shop.ID).Error
require.NoError(t, err)
assert.NotNil(t, deletedShop.DeletedAt)
}
@@ -460,11 +460,11 @@ func TestShopAccount_FilterByStatus(t *testing.T) {
defer env.teardown()
// 创建启用和禁用的账号
_ = testutil.CreateTestAccount(t, env.db, "enabled_agent", "pass123", constants.UserTypeAgent, &env.testShop.ID, nil)
disabledAccount := testutil.CreateTestAccount(t, env.db, "disabled_agent", "pass123", constants.UserTypeAgent, &env.testShop.ID, nil)
_ = testutil.CreateTestAccount(t, env.tx, "enabled_agent", "pass123", constants.UserTypeAgent, &env.testShop.ID, nil)
disabledAccount := testutil.CreateTestAccount(t, env.tx, "disabled_agent", "pass123", constants.UserTypeAgent, &env.testShop.ID, nil)
// 禁用第二个账号
env.db.Model(&disabledAccount).Update("status", 2)
env.tx.Model(&disabledAccount).Update("status", 2)
// 查询只包含启用的账号
req := httptest.NewRequest("GET", fmt.Sprintf("/api/admin/shop-accounts?shop_id=%d&status=1", env.testShop.ID), nil)

View File

@@ -29,8 +29,8 @@ import (
// shopManagementTestEnv 商户管理测试环境
type shopManagementTestEnv struct {
db *gorm.DB
redisClient *redis.Client
tx *gorm.DB
rdb *redis.Client
tokenManager *auth.TokenManager
app *fiber.App
adminToken string
@@ -52,12 +52,12 @@ func setupShopManagementTestEnv(t *testing.T) *shopManagementTestEnv {
zapLogger, _ := zap.NewDevelopment()
dsn := "host=cxd.whcxd.cn port=16159 user=erp_pgsql password=erp_2025 dbname=junhong_cmp_test sslmode=disable TimeZone=Asia/Shanghai"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
tx, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
Logger: logger.Default.LogMode(logger.Silent),
})
require.NoError(t, err)
err = db.AutoMigrate(
err = tx.AutoMigrate(
&model.Account{},
&model.Role{},
&model.Permission{},
@@ -69,30 +69,30 @@ func setupShopManagementTestEnv(t *testing.T) *shopManagementTestEnv {
)
require.NoError(t, err)
redisClient := redis.NewClient(&redis.Options{
rdb := redis.NewClient(&redis.Options{
Addr: "cxd.whcxd.cn:16299",
Password: "cpNbWtAaqgo1YJmbMp3h",
DB: 15,
})
ctx := context.Background()
err = redisClient.Ping(ctx).Err()
err = rdb.Ping(ctx).Err()
require.NoError(t, err)
testPrefix := fmt.Sprintf("test:%s:", t.Name())
keys, _ := redisClient.Keys(ctx, testPrefix+"*").Result()
keys, _ := rdb.Keys(ctx, testPrefix+"*").Result()
if len(keys) > 0 {
redisClient.Del(ctx, keys...)
rdb.Del(ctx, keys...)
}
tokenManager := auth.NewTokenManager(redisClient, 24*time.Hour, 7*24*time.Hour)
tokenManager := auth.NewTokenManager(rdb, 24*time.Hour, 7*24*time.Hour)
superAdmin := testutil.CreateSuperAdmin(t, db)
adminToken, _ := testutil.GenerateTestToken(t, redisClient, superAdmin, "web")
superAdmin := testutil.CreateSuperAdmin(t, tx)
adminToken, _ := testutil.GenerateTestToken(t, rdb, superAdmin, "web")
deps := &bootstrap.Dependencies{
DB: db,
Redis: redisClient,
DB: tx,
Redis: rdb,
Logger: zapLogger,
TokenManager: tokenManager,
}
@@ -112,8 +112,8 @@ func setupShopManagementTestEnv(t *testing.T) *shopManagementTestEnv {
routes.RegisterRoutes(app, handlers, middlewares)
return &shopManagementTestEnv{
db: db,
redisClient: redisClient,
tx: tx,
rdb: rdb,
tokenManager: tokenManager,
app: app,
adminToken: adminToken,
@@ -124,17 +124,17 @@ func setupShopManagementTestEnv(t *testing.T) *shopManagementTestEnv {
// teardown 清理测试环境
func (e *shopManagementTestEnv) teardown() {
e.db.Exec("DELETE FROM tb_account WHERE username LIKE 'test%' OR username LIKE 'agent%' OR username LIKE 'superadmin%'")
e.db.Exec("DELETE FROM tb_shop WHERE shop_code LIKE 'TEST%' OR shop_code LIKE 'DUP%' OR shop_code LIKE 'SHOP_%' OR shop_code LIKE 'ORIG%' OR shop_code LIKE 'DEL%' OR shop_code LIKE 'MULTI%'")
e.tx.Exec("DELETE FROM tb_account WHERE username LIKE 'test%' OR username LIKE 'agent%' OR username LIKE 'superadmin%'")
e.tx.Exec("DELETE FROM tb_shop WHERE shop_code LIKE 'TEST%' OR shop_code LIKE 'DUP%' OR shop_code LIKE 'SHOP_%' OR shop_code LIKE 'ORIG%' OR shop_code LIKE 'DEL%' OR shop_code LIKE 'MULTI%'")
ctx := context.Background()
testPrefix := fmt.Sprintf("test:%s:", e.t.Name())
keys, _ := e.redisClient.Keys(ctx, testPrefix+"*").Result()
keys, _ := e.rdb.Keys(ctx, testPrefix+"*").Result()
if len(keys) > 0 {
e.redisClient.Del(ctx, keys...)
e.rdb.Del(ctx, keys...)
}
e.redisClient.Close()
e.rdb.Close()
}
// TestShopManagement_CreateShop 测试创建商户
@@ -245,9 +245,9 @@ func TestShopManagement_ListShops(t *testing.T) {
defer env.teardown()
// 创建测试数据
testutil.CreateTestShop(t, env.db, "商户A", "SHOP_A", 1, nil)
testutil.CreateTestShop(t, env.db, "商户B", "SHOP_B", 1, nil)
testutil.CreateTestShop(t, env.db, "商户C", "SHOP_C", 2, nil)
testutil.CreateTestShop(t, env.tx, "商户A", "SHOP_A", 1, nil)
testutil.CreateTestShop(t, env.tx, "商户B", "SHOP_B", 1, nil)
testutil.CreateTestShop(t, env.tx, "商户C", "SHOP_C", 2, nil)
req := httptest.NewRequest("GET", "/api/admin/shops?page=1&size=10", nil)
req.Header.Set("Authorization", "Bearer "+env.adminToken)
@@ -279,7 +279,7 @@ func TestShopManagement_UpdateShop(t *testing.T) {
defer env.teardown()
// 创建测试商户
shop := testutil.CreateTestShop(t, env.db, "原始商户", "ORIG001", 1, nil)
shop := testutil.CreateTestShop(t, env.tx, "原始商户", "ORIG001", 1, nil)
// 更新商户
reqBody := dto.UpdateShopRequest{
@@ -318,7 +318,7 @@ func TestShopManagement_DeleteShop(t *testing.T) {
defer env.teardown()
// 创建测试商户
shop := testutil.CreateTestShop(t, env.db, "待删除商户", "DEL001", 1, nil)
shop := testutil.CreateTestShop(t, env.tx, "待删除商户", "DEL001", 1, nil)
// 删除商户
req := httptest.NewRequest("DELETE", fmt.Sprintf("/api/admin/shops/%d", shop.ID), nil)
@@ -343,7 +343,7 @@ func TestShopManagement_DeleteShop_WithMultipleAccounts(t *testing.T) {
defer env.teardown()
// 创建测试商户
shop := testutil.CreateTestShop(t, env.db, "多账号商户", "MULTI001", 1, nil)
shop := testutil.CreateTestShop(t, env.tx, "多账号商户", "MULTI001", 1, nil)
// 删除商户
req := httptest.NewRequest("DELETE", fmt.Sprintf("/api/admin/shops/%d", shop.ID), nil)

View File

@@ -26,14 +26,14 @@ type EmailPayload struct {
// TestTaskSubmit 测试任务提交
func TestTaskSubmit(t *testing.T) {
// 创建 Redis 客户端
redisClient := redis.NewClient(&redis.Options{
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
})
defer func() { _ = redisClient.Close() }()
defer func() { _ = rdb.Close() }()
// 清理测试数据
ctx := context.Background()
redisClient.FlushDB(ctx)
rdb.FlushDB(ctx)
// 创建 Asynq 客户端
client := asynq.NewClient(asynq.RedisClientOpt{
@@ -69,13 +69,13 @@ func TestTaskSubmit(t *testing.T) {
// TestTaskPriority 测试任务优先级
func TestTaskPriority(t *testing.T) {
// 创建 Redis 客户端
redisClient := redis.NewClient(&redis.Options{
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
})
defer func() { _ = redisClient.Close() }()
defer func() { _ = rdb.Close() }()
ctx := context.Background()
redisClient.FlushDB(ctx)
rdb.FlushDB(ctx)
// 创建 Asynq 客户端
client := asynq.NewClient(asynq.RedisClientOpt{
@@ -115,13 +115,13 @@ func TestTaskPriority(t *testing.T) {
// TestTaskRetry 测试任务重试机制
func TestTaskRetry(t *testing.T) {
redisClient := redis.NewClient(&redis.Options{
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
})
defer func() { _ = redisClient.Close() }()
defer func() { _ = rdb.Close() }()
ctx := context.Background()
redisClient.FlushDB(ctx)
rdb.FlushDB(ctx)
client := asynq.NewClient(asynq.RedisClientOpt{
Addr: "localhost:6379",
@@ -152,34 +152,34 @@ func TestTaskRetry(t *testing.T) {
// TestTaskIdempotency 测试任务幂等性键
func TestTaskIdempotency(t *testing.T) {
redisClient := redis.NewClient(&redis.Options{
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
})
defer func() { _ = redisClient.Close() }()
defer func() { _ = rdb.Close() }()
ctx := context.Background()
redisClient.FlushDB(ctx)
rdb.FlushDB(ctx)
requestID := "idempotent-test-001"
lockKey := constants.RedisTaskLockKey(requestID)
// 第一次设置锁(模拟任务开始执行)
result, err := redisClient.SetNX(ctx, lockKey, "1", 24*time.Hour).Result()
result, err := rdb.SetNX(ctx, lockKey, "1", 24*time.Hour).Result()
require.NoError(t, err)
assert.True(t, result, "第一次设置锁应该成功")
// 第二次设置锁(模拟重复任务)
result, err = redisClient.SetNX(ctx, lockKey, "1", 24*time.Hour).Result()
result, err = rdb.SetNX(ctx, lockKey, "1", 24*time.Hour).Result()
require.NoError(t, err)
assert.False(t, result, "第二次设置锁应该失败(幂等性)")
// 验证锁存在
exists, err := redisClient.Exists(ctx, lockKey).Result()
exists, err := rdb.Exists(ctx, lockKey).Result()
require.NoError(t, err)
assert.Equal(t, int64(1), exists)
// 验证 TTL
ttl, err := redisClient.TTL(ctx, lockKey).Result()
ttl, err := rdb.TTL(ctx, lockKey).Result()
require.NoError(t, err)
assert.Greater(t, ttl.Hours(), 23.0)
assert.LessOrEqual(t, ttl.Hours(), 24.0)
@@ -187,13 +187,13 @@ func TestTaskIdempotency(t *testing.T) {
// TestTaskStatusTracking 测试任务状态跟踪
func TestTaskStatusTracking(t *testing.T) {
redisClient := redis.NewClient(&redis.Options{
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
})
defer func() { _ = redisClient.Close() }()
defer func() { _ = rdb.Close() }()
ctx := context.Background()
redisClient.FlushDB(ctx)
rdb.FlushDB(ctx)
taskID := "task-123456"
statusKey := constants.RedisTaskStatusKey(taskID)
@@ -202,30 +202,30 @@ func TestTaskStatusTracking(t *testing.T) {
statuses := []string{"pending", "processing", "completed"}
for _, status := range statuses {
err := redisClient.Set(ctx, statusKey, status, 7*24*time.Hour).Err()
err := rdb.Set(ctx, statusKey, status, 7*24*time.Hour).Err()
require.NoError(t, err)
// 读取状态
result, err := redisClient.Get(ctx, statusKey).Result()
result, err := rdb.Get(ctx, statusKey).Result()
require.NoError(t, err)
assert.Equal(t, status, result)
}
// 验证 TTL
ttl, err := redisClient.TTL(ctx, statusKey).Result()
ttl, err := rdb.TTL(ctx, statusKey).Result()
require.NoError(t, err)
assert.Greater(t, ttl.Hours(), 24.0*6)
}
// TestQueueInspection 测试队列检查
func TestQueueInspection(t *testing.T) {
redisClient := redis.NewClient(&redis.Options{
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
})
defer func() { _ = redisClient.Close() }()
defer func() { _ = rdb.Close() }()
ctx := context.Background()
redisClient.FlushDB(ctx)
rdb.FlushDB(ctx)
client := asynq.NewClient(asynq.RedisClientOpt{
Addr: "localhost:6379",