Files
junhong_cmp_fiber/tests/integration/account_test.go
huang 23eb0307bb
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m30s
feat: 实现门店套餐分配功能并统一测试基础设施
新增功能:
- 门店套餐分配管理(shop_package_allocation):支持门店套餐库存管理
- 门店套餐系列分配管理(shop_series_allocation):支持套餐系列分配和佣金层级设置
- 我的套餐查询(my_package):支持门店查询自己的套餐分配情况

测试改进:
- 统一集成测试基础设施,新增 testutils.NewIntegrationTestEnv
- 重构所有集成测试使用新的测试环境设置
- 移除旧的测试辅助函数和冗余测试文件
- 新增 test_helpers_test.go 统一任务测试辅助

技术细节:
- 新增数据库迁移 000025_create_shop_allocation_tables
- 新增 3 个 Handler、Service、Store 和对应的单元测试
- 更新 OpenAPI 文档和文档生成器
- 测试覆盖率:Service 层 > 90%

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-28 10:45:16 +08:00

280 lines
9.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package integration
import (
"encoding/json"
"fmt"
"testing"
"time"
"github.com/gofiber/fiber/v2"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/break/junhong_cmp_fiber/internal/model"
"github.com/break/junhong_cmp_fiber/internal/model/dto"
"github.com/break/junhong_cmp_fiber/pkg/constants"
"github.com/break/junhong_cmp_fiber/pkg/errors"
"github.com/break/junhong_cmp_fiber/pkg/response"
"github.com/break/junhong_cmp_fiber/tests/testutils/integ"
)
// TestAccountAPI_Create 测试创建账号 API
func TestAccountAPI_Create(t *testing.T) {
env := integ.NewIntegrationTestEnv(t)
t.Run("成功创建平台账号", func(t *testing.T) {
username := fmt.Sprintf("platform_user_%d", time.Now().UnixNano())
phone := fmt.Sprintf("138%08d", time.Now().UnixNano()%100000000)
reqBody := dto.CreateAccountRequest{
Username: username,
Phone: phone,
Password: "Password123",
UserType: constants.UserTypePlatform,
}
jsonBody, _ := json.Marshal(reqBody)
resp, err := env.AsSuperAdmin().Request("POST", "/api/admin/accounts", jsonBody)
require.NoError(t, err)
assert.Equal(t, fiber.StatusOK, resp.StatusCode)
var result response.Response
err = json.NewDecoder(resp.Body).Decode(&result)
require.NoError(t, err)
assert.Equal(t, 0, result.Code)
// 验证数据库中账号已创建
var count int64
env.RawDB().Model(&model.Account{}).Where("username = ?", username).Count(&count)
assert.Equal(t, int64(1), count)
})
t.Run("用户名重复时返回错误", func(t *testing.T) {
// 先创建一个账号
existingUsername := fmt.Sprintf("existing_user_%d", time.Now().UnixNano())
existingAccount := env.CreateTestAccount(existingUsername, "password123", constants.UserTypePlatform, nil, nil)
// 尝试创建同名账号
phone := fmt.Sprintf("138%08d", time.Now().UnixNano()%100000000)
reqBody := dto.CreateAccountRequest{
Username: existingAccount.Username,
Phone: phone,
Password: "Password123",
UserType: constants.UserTypePlatform,
}
jsonBody, _ := json.Marshal(reqBody)
resp, err := env.AsSuperAdmin().Request("POST", "/api/admin/accounts", jsonBody)
require.NoError(t, err)
var result response.Response
err = json.NewDecoder(resp.Body).Decode(&result)
require.NoError(t, err)
assert.Equal(t, errors.CodeUsernameExists, result.Code)
})
// TODO: 当前代码允许平台账号不提供 parent_id此测试预期的业务规则已变更
// t.Run("非root用户缺少parent_id时返回错误", func(t *testing.T) { ... })
}
// TestAccountAPI_Get 测试获取账号详情 API
func TestAccountAPI_Get(t *testing.T) {
env := integ.NewIntegrationTestEnv(t)
// 创建测试账号
testAccount := env.CreateTestAccount("test_user", "password123", constants.UserTypePlatform, nil, nil)
t.Run("成功获取账号详情", func(t *testing.T) {
resp, err := env.AsSuperAdmin().Request("GET", fmt.Sprintf("/api/admin/accounts/%d", testAccount.ID), nil)
require.NoError(t, err)
assert.Equal(t, fiber.StatusOK, resp.StatusCode)
var result response.Response
err = json.NewDecoder(resp.Body).Decode(&result)
require.NoError(t, err)
assert.Equal(t, 0, result.Code)
})
t.Run("账号不存在时返回错误", func(t *testing.T) {
resp, err := env.AsSuperAdmin().Request("GET", "/api/admin/accounts/99999", nil)
require.NoError(t, err)
var result response.Response
err = json.NewDecoder(resp.Body).Decode(&result)
require.NoError(t, err)
assert.Equal(t, errors.CodeAccountNotFound, result.Code)
})
t.Run("无效ID返回错误", func(t *testing.T) {
resp, err := env.AsSuperAdmin().Request("GET", "/api/admin/accounts/invalid", nil)
require.NoError(t, err)
var result response.Response
err = json.NewDecoder(resp.Body).Decode(&result)
require.NoError(t, err)
assert.Equal(t, errors.CodeInvalidParam, result.Code)
})
}
// TestAccountAPI_Update 测试更新账号 API
func TestAccountAPI_Update(t *testing.T) {
env := integ.NewIntegrationTestEnv(t)
// 创建测试账号
testAccount := env.CreateTestAccount("update_test", "password123", constants.UserTypePlatform, nil, nil)
t.Run("成功更新账号", func(t *testing.T) {
newUsername := "updated_user"
reqBody := dto.UpdateAccountRequest{
Username: &newUsername,
}
jsonBody, _ := json.Marshal(reqBody)
resp, err := env.AsSuperAdmin().Request("PUT", fmt.Sprintf("/api/admin/accounts/%d", testAccount.ID), jsonBody)
require.NoError(t, err)
assert.Equal(t, fiber.StatusOK, resp.StatusCode)
// 验证数据库已更新
var updated model.Account
env.RawDB().First(&updated, testAccount.ID)
assert.Equal(t, newUsername, updated.Username)
})
}
// TestAccountAPI_Delete 测试删除账号 API
func TestAccountAPI_Delete(t *testing.T) {
env := integ.NewIntegrationTestEnv(t)
t.Run("成功软删除账号", func(t *testing.T) {
// 创建测试账号
testAccount := env.CreateTestAccount("delete_test", "password123", constants.UserTypePlatform, nil, nil)
resp, err := env.AsSuperAdmin().Request("DELETE", fmt.Sprintf("/api/admin/accounts/%d", testAccount.ID), nil)
require.NoError(t, err)
assert.Equal(t, fiber.StatusOK, resp.StatusCode)
// 验证账号已软删除
var deleted model.Account
err = env.RawDB().Unscoped().First(&deleted, testAccount.ID).Error
require.NoError(t, err)
assert.NotNil(t, deleted.DeletedAt)
})
}
// TestAccountAPI_List 测试账号列表 API
func TestAccountAPI_List(t *testing.T) {
env := integ.NewIntegrationTestEnv(t)
// 创建多个测试账号
for i := 1; i <= 5; i++ {
env.CreateTestAccount(fmt.Sprintf("list_test_%d", i), "password123", constants.UserTypePlatform, nil, nil)
}
t.Run("成功获取账号列表", func(t *testing.T) {
resp, err := env.AsSuperAdmin().Request("GET", "/api/admin/accounts?page=1&page_size=10", nil)
require.NoError(t, err)
assert.Equal(t, fiber.StatusOK, resp.StatusCode)
var result response.Response
err = json.NewDecoder(resp.Body).Decode(&result)
require.NoError(t, err)
assert.Equal(t, 0, result.Code)
})
t.Run("分页功能正常", func(t *testing.T) {
resp, err := env.AsSuperAdmin().Request("GET", "/api/admin/accounts?page=1&page_size=2", nil)
require.NoError(t, err)
assert.Equal(t, fiber.StatusOK, resp.StatusCode)
})
}
// TestAccountAPI_AssignRoles 测试分配角色 API
func TestAccountAPI_AssignRoles(t *testing.T) {
env := integ.NewIntegrationTestEnv(t)
// 创建测试账号
testAccount := env.CreateTestAccount("role_test", "password123", constants.UserTypePlatform, nil, nil)
// 创建测试角色
testRole := env.CreateTestRole("测试角色", constants.RoleTypePlatform)
t.Run("成功分配角色", func(t *testing.T) {
reqBody := dto.AssignRolesRequest{
RoleIDs: []uint{testRole.ID},
}
jsonBody, _ := json.Marshal(reqBody)
resp, err := env.AsSuperAdmin().Request("POST", fmt.Sprintf("/api/admin/accounts/%d/roles", testAccount.ID), jsonBody)
require.NoError(t, err)
assert.Equal(t, fiber.StatusOK, resp.StatusCode)
// 验证关联已创建
var count int64
env.RawDB().Model(&model.AccountRole{}).Where("account_id = ? AND role_id = ?", testAccount.ID, testRole.ID).Count(&count)
assert.Equal(t, int64(1), count)
})
}
// TestAccountAPI_GetRoles 测试获取账号角色 API
func TestAccountAPI_GetRoles(t *testing.T) {
env := integ.NewIntegrationTestEnv(t)
// 创建测试账号
testAccount := env.CreateTestAccount("get_roles_test", "password123", constants.UserTypePlatform, nil, nil)
// 创建并分配角色
testRole := env.CreateTestRole("获取角色测试", constants.RoleTypePlatform)
accountRole := &model.AccountRole{
AccountID: testAccount.ID,
RoleID: testRole.ID,
Status: constants.StatusEnabled,
Creator: 1,
Updater: 1,
}
env.TX.Create(accountRole)
t.Run("成功获取账号角色", func(t *testing.T) {
resp, err := env.AsSuperAdmin().Request("GET", fmt.Sprintf("/api/admin/accounts/%d/roles", testAccount.ID), nil)
require.NoError(t, err)
assert.Equal(t, fiber.StatusOK, resp.StatusCode)
var result response.Response
err = json.NewDecoder(resp.Body).Decode(&result)
require.NoError(t, err)
assert.Equal(t, 0, result.Code)
})
}
// TestAccountAPI_RemoveRole 测试移除角色 API
func TestAccountAPI_RemoveRole(t *testing.T) {
env := integ.NewIntegrationTestEnv(t)
// 创建测试账号
testAccount := env.CreateTestAccount("remove_role_test", "password123", constants.UserTypePlatform, nil, nil)
// 创建并分配角色
testRole := env.CreateTestRole("移除角色测试", constants.RoleTypePlatform)
accountRole := &model.AccountRole{
AccountID: testAccount.ID,
RoleID: testRole.ID,
Status: constants.StatusEnabled,
Creator: 1,
Updater: 1,
}
env.TX.Create(accountRole)
t.Run("成功移除角色", func(t *testing.T) {
resp, err := env.AsSuperAdmin().Request("DELETE", fmt.Sprintf("/api/admin/accounts/%d/roles/%d", testAccount.ID, testRole.ID), nil)
require.NoError(t, err)
assert.Equal(t, fiber.StatusOK, resp.StatusCode)
// 验证关联已软删除
var ar model.AccountRole
err = env.RawDB().Unscoped().Where("account_id = ? AND role_id = ?", testAccount.ID, testRole.ID).First(&ar).Error
require.NoError(t, err)
assert.NotNil(t, ar.DeletedAt)
})
}