重构: 使用 testutils.NewIntegrationTestEnv 替换旧的测试环境设置

- 移除 setupAuthorizationTestEnv 和 teardown 函数
- 移除所有 DELETE 清理代码,改用事务隔离
- 每个测试函数改用 env := testutils.NewIntegrationTestEnv(t)
- 使用 env.TX 替代 env.db
- 使用 env.AsSuperAdmin().Request() 和 env.AsUser() 发送请求
- 使用 env.CreateTestShop/Enterprise/Account 创建测试数据
- 移除未使用的导入(bytes, net/http/httptest)
- 保持所有测试业务逻辑不变
This commit is contained in:
2026-01-27 22:44:21 +08:00
parent 79c061b6fa
commit 5fefe9d0cb

View File

@@ -1,150 +1,26 @@
package integration
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http/httptest"
"testing"
"time"
"github.com/break/junhong_cmp_fiber/internal/bootstrap"
internalMiddleware "github.com/break/junhong_cmp_fiber/internal/middleware"
"github.com/break/junhong_cmp_fiber/internal/model"
"github.com/break/junhong_cmp_fiber/internal/routes"
"github.com/break/junhong_cmp_fiber/pkg/auth"
"github.com/break/junhong_cmp_fiber/pkg/config"
"github.com/break/junhong_cmp_fiber/pkg/constants"
"github.com/break/junhong_cmp_fiber/pkg/queue"
"github.com/break/junhong_cmp_fiber/pkg/response"
"github.com/break/junhong_cmp_fiber/tests/testutil"
"github.com/gofiber/fiber/v2"
"github.com/redis/go-redis/v9"
"github.com/break/junhong_cmp_fiber/tests/testutils"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
const (
testDBDSN = "host=cxd.whcxd.cn port=16159 user=erp_pgsql password=erp_2025 dbname=junhong_cmp_test sslmode=disable TimeZone=Asia/Shanghai"
testRedisAddr = "cxd.whcxd.cn:16299"
testRedisPasswd = "cpNbWtAaqgo1YJmbMp3h"
testRedisDB = 6
)
type authorizationTestEnv struct {
db *gorm.DB
rdb *redis.Client
tokenManager *auth.TokenManager
app *fiber.App
adminToken string
agentToken string
enterprise *model.Enterprise
card1 *model.IotCard
card2 *model.IotCard
auth1 *model.EnterpriseCardAuthorization
shop *model.Shop
agentAccount *model.Account
t *testing.T
}
func setupTestEnvVars(t *testing.T) {
t.Helper()
t.Setenv("JUNHONG_DATABASE_HOST", "cxd.whcxd.cn")
t.Setenv("JUNHONG_DATABASE_PORT", "16159")
t.Setenv("JUNHONG_DATABASE_USER", "erp_pgsql")
t.Setenv("JUNHONG_DATABASE_PASSWORD", "erp_2025")
t.Setenv("JUNHONG_DATABASE_DBNAME", "junhong_cmp_test")
t.Setenv("JUNHONG_DATABASE_SSLMODE", "disable")
t.Setenv("JUNHONG_REDIS_ADDRESS", "cxd.whcxd.cn")
t.Setenv("JUNHONG_REDIS_PORT", "16299")
t.Setenv("JUNHONG_REDIS_PASSWORD", "cpNbWtAaqgo1YJmbMp3h")
t.Setenv("JUNHONG_REDIS_DB", "6")
t.Setenv("JUNHONG_JWT_SECRET_KEY", "dev-secret-key-for-testing-only-32chars!")
t.Setenv("JUNHONG_SERVER_ADDRESS", ":3000")
t.Setenv("JUNHONG_LOGGING_LEVEL", "debug")
t.Setenv("JUNHONG_LOGGING_DEVELOPMENT", "true")
}
func setupAuthorizationTestEnv(t *testing.T) *authorizationTestEnv {
t.Helper()
setupTestEnvVars(t)
cfg, err := config.Load()
require.NoError(t, err)
err = config.Set(cfg)
require.NoError(t, err)
zapLogger, _ := zap.NewDevelopment()
db, err := gorm.Open(postgres.Open(testDBDSN), &gorm.Config{
Logger: logger.Default.LogMode(logger.Silent),
})
require.NoError(t, err)
rdb := redis.NewClient(&redis.Options{
Addr: testRedisAddr,
Password: testRedisPasswd,
DB: testRedisDB,
})
ctx := context.Background()
err = rdb.Ping(ctx).Err()
require.NoError(t, err)
testPrefix := fmt.Sprintf("test:%s:", t.Name())
keys, _ := rdb.Keys(ctx, testPrefix+"*").Result()
if len(keys) > 0 {
rdb.Del(ctx, keys...)
}
tokenManager := auth.NewTokenManager(rdb, 24*time.Hour, 7*24*time.Hour)
superAdmin := testutil.CreateSuperAdmin(t, db)
adminToken, _ := testutil.GenerateTestToken(t, rdb, superAdmin, "web")
queueClient := queue.NewClient(rdb, zapLogger)
deps := &bootstrap.Dependencies{
DB: db,
Redis: rdb,
Logger: zapLogger,
TokenManager: tokenManager,
QueueClient: queueClient,
}
result, err := bootstrap.Bootstrap(deps)
require.NoError(t, err)
app := fiber.New(fiber.Config{
ErrorHandler: internalMiddleware.ErrorHandler(zapLogger),
})
routes.RegisterRoutes(app, result.Handlers, result.Middlewares)
func TestAuthorization_List(t *testing.T) {
env := testutils.NewIntegrationTestEnv(t)
ts := time.Now().Unix() % 100000
shop := &model.Shop{
ShopName: "AUTH_TEST_SHOP",
ShopCode: fmt.Sprintf("AS%d", ts),
Level: 1,
Status: constants.StatusEnabled,
}
shop.Creator = superAdmin.ID
shop.Updater = superAdmin.ID
require.NoError(t, db.Create(shop).Error)
shop := env.CreateTestShop("AUTH_TEST_SHOP", 1, nil)
enterprise := &model.Enterprise{
EnterpriseName: "AUTH_TEST_ENTERPRISE",
EnterpriseCode: fmt.Sprintf("AE%d", ts),
OwnerShopID: &shop.ID,
Status: constants.StatusEnabled,
}
enterprise.Creator = superAdmin.ID
enterprise.Updater = superAdmin.ID
require.NoError(t, db.Create(enterprise).Error)
enterprise := env.CreateTestEnterprise("AUTH_TEST_ENTERPRISE", &shop.ID)
card1 := &model.IotCard{
ICCID: fmt.Sprintf("AC1%d", ts),
@@ -160,77 +36,22 @@ func setupAuthorizationTestEnv(t *testing.T) *authorizationTestEnv {
Status: 1,
ShopID: &shop.ID,
}
require.NoError(t, db.Create(card1).Error)
require.NoError(t, db.Create(card2).Error)
require.NoError(t, env.TX.Create(card1).Error)
require.NoError(t, env.TX.Create(card2).Error)
now := time.Now()
auth1 := &model.EnterpriseCardAuthorization{
EnterpriseID: enterprise.ID,
CardID: card1.ID,
AuthorizedBy: superAdmin.ID,
AuthorizedBy: 1,
AuthorizedAt: now,
AuthorizerType: constants.UserTypePlatform,
Remark: "集成测试授权记录",
}
require.NoError(t, db.Create(auth1).Error)
agentAccount := &model.Account{
Username: fmt.Sprintf("aa%d", ts),
Phone: fmt.Sprintf("138%05d", ts),
Password: "hashed_password",
UserType: constants.UserTypeAgent,
ShopID: &shop.ID,
Status: constants.StatusEnabled,
}
agentAccount.Creator = superAdmin.ID
agentAccount.Updater = superAdmin.ID
require.NoError(t, db.Create(agentAccount).Error)
agentToken, _ := testutil.GenerateTestToken(t, rdb, agentAccount, "web")
return &authorizationTestEnv{
db: db,
rdb: rdb,
tokenManager: tokenManager,
app: app,
adminToken: adminToken,
agentToken: agentToken,
enterprise: enterprise,
card1: card1,
card2: card2,
auth1: auth1,
shop: shop,
agentAccount: agentAccount,
t: t,
}
}
func (e *authorizationTestEnv) teardown() {
e.db.Exec("DELETE FROM tb_enterprise_card_authorization WHERE enterprise_id = ?", e.enterprise.ID)
e.db.Exec("DELETE FROM tb_iot_card WHERE iccid LIKE 'AC%'")
e.db.Exec("DELETE FROM tb_enterprise WHERE enterprise_code LIKE 'AE%'")
e.db.Exec("DELETE FROM tb_account WHERE username LIKE 'aa%'")
e.db.Exec("DELETE FROM tb_shop WHERE shop_code LIKE 'AS%'")
ctx := context.Background()
testPrefix := fmt.Sprintf("test:%s:", e.t.Name())
keys, _ := e.rdb.Keys(ctx, testPrefix+"*").Result()
if len(keys) > 0 {
e.rdb.Del(ctx, keys...)
}
e.rdb.Close()
}
func TestAuthorization_List(t *testing.T) {
env := setupAuthorizationTestEnv(t)
defer env.teardown()
require.NoError(t, env.TX.Create(auth1).Error)
t.Run("平台用户获取授权记录列表", func(t *testing.T) {
req := httptest.NewRequest("GET", "/api/admin/authorizations?page=1&page_size=20", nil)
req.Header.Set("Authorization", "Bearer "+env.adminToken)
resp, err := env.app.Test(req, -1)
resp, err := env.AsSuperAdmin().Request("GET", "/api/admin/authorizations?page=1&page_size=20", nil)
require.NoError(t, err)
defer resp.Body.Close()
@@ -249,11 +70,8 @@ func TestAuthorization_List(t *testing.T) {
})
t.Run("按企业ID筛选授权记录", func(t *testing.T) {
url := fmt.Sprintf("/api/admin/authorizations?enterprise_id=%d&page=1&page_size=20", env.enterprise.ID)
req := httptest.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer "+env.adminToken)
resp, err := env.app.Test(req, -1)
url := fmt.Sprintf("/api/admin/authorizations?enterprise_id=%d&page=1&page_size=20", enterprise.ID)
resp, err := env.AsSuperAdmin().Request("GET", url, nil)
require.NoError(t, err)
defer resp.Body.Close()
@@ -270,11 +88,8 @@ func TestAuthorization_List(t *testing.T) {
})
t.Run("按ICCID筛选授权记录", func(t *testing.T) {
url := fmt.Sprintf("/api/admin/authorizations?iccid=%s&page=1&page_size=20", env.card1.ICCID)
req := httptest.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer "+env.adminToken)
resp, err := env.app.Test(req, -1)
url := fmt.Sprintf("/api/admin/authorizations?iccid=%s&page=1&page_size=20", card1.ICCID)
resp, err := env.AsSuperAdmin().Request("GET", url, nil)
require.NoError(t, err)
defer resp.Body.Close()
@@ -291,11 +106,8 @@ func TestAuthorization_List(t *testing.T) {
})
t.Run("按状态筛选-有效授权", func(t *testing.T) {
url := fmt.Sprintf("/api/admin/authorizations?enterprise_id=%d&status=1&page=1&page_size=20", env.enterprise.ID)
req := httptest.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer "+env.adminToken)
resp, err := env.app.Test(req, -1)
url := fmt.Sprintf("/api/admin/authorizations?enterprise_id=%d&status=1&page=1&page_size=20", enterprise.ID)
resp, err := env.AsSuperAdmin().Request("GET", url, nil)
require.NoError(t, err)
defer resp.Body.Close()
@@ -309,15 +121,36 @@ func TestAuthorization_List(t *testing.T) {
}
func TestAuthorization_GetDetail(t *testing.T) {
env := setupAuthorizationTestEnv(t)
defer env.teardown()
env := testutils.NewIntegrationTestEnv(t)
ts := time.Now().Unix() % 100000
shop := env.CreateTestShop("AUTH_TEST_SHOP", 1, nil)
enterprise := env.CreateTestEnterprise("AUTH_TEST_ENTERPRISE", &shop.ID)
card1 := &model.IotCard{
ICCID: fmt.Sprintf("AC1%d", ts),
MSISDN: "13800001001",
CardType: "data_card",
Status: 1,
ShopID: &shop.ID,
}
require.NoError(t, env.TX.Create(card1).Error)
now := time.Now()
auth1 := &model.EnterpriseCardAuthorization{
EnterpriseID: enterprise.ID,
CardID: card1.ID,
AuthorizedBy: 1,
AuthorizedAt: now,
AuthorizerType: constants.UserTypePlatform,
Remark: "集成测试授权记录",
}
require.NoError(t, env.TX.Create(auth1).Error)
t.Run("获取授权记录详情", func(t *testing.T) {
url := fmt.Sprintf("/api/admin/authorizations/%d", env.auth1.ID)
req := httptest.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer "+env.adminToken)
resp, err := env.app.Test(req, -1)
url := fmt.Sprintf("/api/admin/authorizations/%d", auth1.ID)
resp, err := env.AsSuperAdmin().Request("GET", url, nil)
require.NoError(t, err)
defer resp.Body.Close()
@@ -329,19 +162,16 @@ func TestAuthorization_GetDetail(t *testing.T) {
assert.Equal(t, 0, result.Code)
data := result.Data.(map[string]interface{})
assert.Equal(t, float64(env.auth1.ID), data["id"])
assert.Equal(t, float64(env.enterprise.ID), data["enterprise_id"])
assert.Equal(t, float64(auth1.ID), data["id"])
assert.Equal(t, float64(enterprise.ID), data["enterprise_id"])
assert.Equal(t, "AUTH_TEST_ENTERPRISE", data["enterprise_name"])
assert.Equal(t, env.card1.ICCID, data["iccid"])
assert.Equal(t, card1.ICCID, data["iccid"])
assert.Equal(t, "集成测试授权记录", data["remark"])
assert.Equal(t, float64(1), data["status"])
})
t.Run("获取不存在的授权记录", func(t *testing.T) {
req := httptest.NewRequest("GET", "/api/admin/authorizations/999999", nil)
req.Header.Set("Authorization", "Bearer "+env.adminToken)
resp, err := env.app.Test(req, -1)
resp, err := env.AsSuperAdmin().Request("GET", "/api/admin/authorizations/999999", nil)
require.NoError(t, err)
defer resp.Body.Close()
@@ -355,19 +185,39 @@ func TestAuthorization_GetDetail(t *testing.T) {
}
func TestAuthorization_UpdateRemark(t *testing.T) {
env := setupAuthorizationTestEnv(t)
defer env.teardown()
env := testutils.NewIntegrationTestEnv(t)
ts := time.Now().Unix() % 100000
shop := env.CreateTestShop("AUTH_TEST_SHOP", 1, nil)
enterprise := env.CreateTestEnterprise("AUTH_TEST_ENTERPRISE", &shop.ID)
card1 := &model.IotCard{
ICCID: fmt.Sprintf("AC1%d", ts),
MSISDN: "13800001001",
CardType: "data_card",
Status: 1,
ShopID: &shop.ID,
}
require.NoError(t, env.TX.Create(card1).Error)
now := time.Now()
auth1 := &model.EnterpriseCardAuthorization{
EnterpriseID: enterprise.ID,
CardID: card1.ID,
AuthorizedBy: 1,
AuthorizedAt: now,
AuthorizerType: constants.UserTypePlatform,
Remark: "集成测试授权记录",
}
require.NoError(t, env.TX.Create(auth1).Error)
t.Run("更新授权记录备注", func(t *testing.T) {
url := fmt.Sprintf("/api/admin/authorizations/%d/remark", env.auth1.ID)
url := fmt.Sprintf("/api/admin/authorizations/%d/remark", auth1.ID)
body := map[string]string{"remark": "更新后的备注内容"}
bodyBytes, _ := json.Marshal(body)
req := httptest.NewRequest("PUT", url, bytes.NewReader(bodyBytes))
req.Header.Set("Authorization", "Bearer "+env.adminToken)
req.Header.Set("Content-Type", "application/json")
resp, err := env.app.Test(req, -1)
resp, err := env.AsSuperAdmin().Request("PUT", url, bodyBytes)
require.NoError(t, err)
defer resp.Body.Close()
@@ -386,11 +236,7 @@ func TestAuthorization_UpdateRemark(t *testing.T) {
body := map[string]string{"remark": "不会更新"}
bodyBytes, _ := json.Marshal(body)
req := httptest.NewRequest("PUT", "/api/admin/authorizations/999999/remark", bytes.NewReader(bodyBytes))
req.Header.Set("Authorization", "Bearer "+env.adminToken)
req.Header.Set("Content-Type", "application/json")
resp, err := env.app.Test(req, -1)
resp, err := env.AsSuperAdmin().Request("PUT", "/api/admin/authorizations/999999/remark", bodyBytes)
require.NoError(t, err)
defer resp.Body.Close()
@@ -399,31 +245,39 @@ func TestAuthorization_UpdateRemark(t *testing.T) {
}
func TestAuthorization_DataPermission(t *testing.T) {
env := setupAuthorizationTestEnv(t)
defer env.teardown()
env := testutils.NewIntegrationTestEnv(t)
ts := time.Now().Unix() % 100000
shop := env.CreateTestShop("AUTH_TEST_SHOP", 1, nil)
enterprise := env.CreateTestEnterprise("AUTH_TEST_ENTERPRISE", &shop.ID)
card1 := &model.IotCard{
ICCID: fmt.Sprintf("AC1%d", ts),
MSISDN: "13800001001",
CardType: "data_card",
Status: 1,
ShopID: &shop.ID,
}
require.NoError(t, env.TX.Create(card1).Error)
now := time.Now()
auth1 := &model.EnterpriseCardAuthorization{
EnterpriseID: enterprise.ID,
CardID: card1.ID,
AuthorizedBy: 1,
AuthorizedAt: now,
AuthorizerType: constants.UserTypePlatform,
Remark: "集成测试授权记录",
}
require.NoError(t, env.TX.Create(auth1).Error)
agentAccount := env.CreateTestAccount("agent", "password123", constants.UserTypeAgent, &shop.ID, nil)
ts2 := time.Now().Unix() % 100000
otherShop := &model.Shop{
ShopName: "OTHER_TEST_SHOP",
ShopCode: fmt.Sprintf("OS%d", ts2),
Level: 1,
Status: constants.StatusEnabled,
}
otherShop.Creator = 1
otherShop.Updater = 1
require.NoError(t, env.db.Create(otherShop).Error)
defer env.db.Exec("DELETE FROM tb_shop WHERE id = ?", otherShop.ID)
otherShop := env.CreateTestShop("OTHER_TEST_SHOP", 1, nil)
otherEnterprise := &model.Enterprise{
EnterpriseName: "OTHER_TEST_ENTERPRISE",
EnterpriseCode: fmt.Sprintf("OE%d", ts2),
OwnerShopID: &otherShop.ID,
Status: constants.StatusEnabled,
}
otherEnterprise.Creator = 1
otherEnterprise.Updater = 1
require.NoError(t, env.db.Create(otherEnterprise).Error)
defer env.db.Exec("DELETE FROM tb_enterprise WHERE id = ?", otherEnterprise.ID)
otherEnterprise := env.CreateTestEnterprise("OTHER_TEST_ENTERPRISE", &otherShop.ID)
otherCard := &model.IotCard{
ICCID: fmt.Sprintf("OC%d", ts2),
@@ -432,10 +286,8 @@ func TestAuthorization_DataPermission(t *testing.T) {
Status: 1,
ShopID: &otherShop.ID,
}
require.NoError(t, env.db.Create(otherCard).Error)
defer env.db.Exec("DELETE FROM tb_iot_card WHERE id = ?", otherCard.ID)
require.NoError(t, env.TX.Create(otherCard).Error)
now := time.Now()
otherAuth := &model.EnterpriseCardAuthorization{
EnterpriseID: otherEnterprise.ID,
CardID: otherCard.ID,
@@ -444,14 +296,10 @@ func TestAuthorization_DataPermission(t *testing.T) {
AuthorizerType: constants.UserTypePlatform,
Remark: "其他店铺的授权记录",
}
require.NoError(t, env.db.Create(otherAuth).Error)
defer env.db.Exec("DELETE FROM tb_enterprise_card_authorization WHERE id = ?", otherAuth.ID)
require.NoError(t, env.TX.Create(otherAuth).Error)
t.Run("代理用户只能看到自己店铺的授权记录", func(t *testing.T) {
req := httptest.NewRequest("GET", "/api/admin/authorizations?page=1&page_size=100", nil)
req.Header.Set("Authorization", "Bearer "+env.agentToken)
resp, err := env.app.Test(req, -1)
resp, err := env.AsUser(agentAccount).Request("GET", "/api/admin/authorizations?page=1&page_size=100", nil)
require.NoError(t, err)
defer resp.Body.Close()
@@ -473,19 +321,16 @@ func TestAuthorization_DataPermission(t *testing.T) {
if authID == otherAuth.ID {
sawOtherAuth = true
}
if authID == env.auth1.ID {
if authID == auth1.ID {
sawOwnAuth = true
}
}
assert.False(t, sawOtherAuth, "代理用户不应该看到其他店铺的授权记录 (otherAuth.ID=%d)", otherAuth.ID)
assert.True(t, sawOwnAuth, "代理用户应该能看到自己店铺的授权记录 (auth1.ID=%d)", env.auth1.ID)
assert.True(t, sawOwnAuth, "代理用户应该能看到自己店铺的授权记录 (auth1.ID=%d)", auth1.ID)
})
t.Run("平台用户可以看到所有授权记录", func(t *testing.T) {
req := httptest.NewRequest("GET", "/api/admin/authorizations?page=1&page_size=100", nil)
req.Header.Set("Authorization", "Bearer "+env.adminToken)
resp, err := env.app.Test(req, -1)
resp, err := env.AsSuperAdmin().Request("GET", "/api/admin/authorizations?page=1&page_size=100", nil)
require.NoError(t, err)
defer resp.Body.Close()
@@ -503,13 +348,10 @@ func TestAuthorization_DataPermission(t *testing.T) {
}
func TestAuthorization_Unauthorized(t *testing.T) {
env := setupAuthorizationTestEnv(t)
defer env.teardown()
env := testutils.NewIntegrationTestEnv(t)
t.Run("无Token访问被拒绝", func(t *testing.T) {
req := httptest.NewRequest("GET", "/api/admin/authorizations", nil)
resp, err := env.app.Test(req, -1)
resp, err := env.ClearAuth().Request("GET", "/api/admin/authorizations", nil)
require.NoError(t, err)
defer resp.Body.Close()
@@ -517,10 +359,9 @@ func TestAuthorization_Unauthorized(t *testing.T) {
})
t.Run("无效Token访问被拒绝", func(t *testing.T) {
req := httptest.NewRequest("GET", "/api/admin/authorizations", nil)
req.Header.Set("Authorization", "Bearer invalid_token")
resp, err := env.app.Test(req, -1)
resp, err := env.RequestWithHeaders("GET", "/api/admin/authorizations", nil, map[string]string{
"Authorization": "Bearer invalid_token",
})
require.NoError(t, err)
defer resp.Body.Close()