From e2e6a64ba4309916c1a6337c4e2a5e220ebd7a67 Mon Sep 17 00:00:00 2001 From: huang Date: Tue, 27 Jan 2026 19:37:08 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9B=E5=BB=BA=20PackageService=20=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95=EF=BC=88=E8=A6=86=E7=9B=96=E5=8F=8C?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E9=80=BB=E8=BE=91=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 创建 internal/service/package/service_test.go 文件 - 测试 Create 方法:创建成功、编码重复失败、系列不存在失败 - 测试 UpdateStatus 方法:禁用时自动强制下架、启用时保持原上架状态 - 测试 UpdateShelfStatus 方法:启用状态可上架、禁用状态不能上架、下架成功 - 测试 Get 方法:获取成功、不存在返回错误 - 测试 List 方法:列表查询、按类型过滤、按状态过滤 - 使用 testutils.NewTestTransaction 创建测试事务 - 使用 middleware.SetUserContext 设置用户上下文 - 使用唯一的 PackageCode(基于时间戳) - 重点覆盖双状态逻辑的测试 --- internal/service/package/service_test.go | 372 +++++++++++++++++++++++ 1 file changed, 372 insertions(+) create mode 100644 internal/service/package/service_test.go diff --git a/internal/service/package/service_test.go b/internal/service/package/service_test.go new file mode 100644 index 0000000..523f63e --- /dev/null +++ b/internal/service/package/service_test.go @@ -0,0 +1,372 @@ +package packagepkg + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/break/junhong_cmp_fiber/internal/model/dto" + "github.com/break/junhong_cmp_fiber/internal/store/postgres" + "github.com/break/junhong_cmp_fiber/pkg/constants" + "github.com/break/junhong_cmp_fiber/pkg/errors" + "github.com/break/junhong_cmp_fiber/pkg/middleware" + "github.com/break/junhong_cmp_fiber/tests/testutils" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func generateUniquePackageCode(prefix string) string { + return fmt.Sprintf("%s_%d", prefix, time.Now().UnixNano()) +} + +func TestPackageService_Create(t *testing.T) { + tx := testutils.NewTestTransaction(t) + packageStore := postgres.NewPackageStore(tx) + packageSeriesStore := postgres.NewPackageSeriesStore(tx) + svc := New(packageStore, packageSeriesStore) + + ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ + UserID: 1, + UserType: constants.UserTypePlatform, + }) + + t.Run("创建成功", func(t *testing.T) { + req := &dto.CreatePackageRequest{ + PackageCode: generateUniquePackageCode("PKG_CREATE"), + PackageName: "创建测试套餐", + PackageType: "formal", + DurationMonths: 1, + Price: 9900, + } + + resp, err := svc.Create(ctx, req) + require.NoError(t, err) + assert.NotZero(t, resp.ID) + assert.Equal(t, req.PackageCode, resp.PackageCode) + assert.Equal(t, req.PackageName, resp.PackageName) + assert.Equal(t, constants.StatusEnabled, resp.Status) + assert.Equal(t, 2, resp.ShelfStatus) + }) + + t.Run("编码重复失败", func(t *testing.T) { + code := generateUniquePackageCode("PKG_DUP") + req1 := &dto.CreatePackageRequest{ + PackageCode: code, + PackageName: "第一个套餐", + PackageType: "formal", + DurationMonths: 1, + Price: 9900, + } + _, err := svc.Create(ctx, req1) + require.NoError(t, err) + + req2 := &dto.CreatePackageRequest{ + PackageCode: code, + PackageName: "第二个套餐", + PackageType: "formal", + DurationMonths: 1, + Price: 9900, + } + _, err = svc.Create(ctx, req2) + require.Error(t, err) + appErr, ok := err.(*errors.AppError) + require.True(t, ok) + assert.Equal(t, errors.CodeConflict, appErr.Code) + }) + + t.Run("系列不存在失败", func(t *testing.T) { + req := &dto.CreatePackageRequest{ + PackageCode: generateUniquePackageCode("PKG_SERIES"), + PackageName: "系列测试套餐", + PackageType: "formal", + DurationMonths: 1, + Price: 9900, + SeriesID: func() *uint { id := uint(99999); return &id }(), + } + + _, err := svc.Create(ctx, req) + require.Error(t, err) + appErr, ok := err.(*errors.AppError) + require.True(t, ok) + assert.Equal(t, errors.CodeNotFound, appErr.Code) + }) +} + +func TestPackageService_UpdateStatus(t *testing.T) { + tx := testutils.NewTestTransaction(t) + packageStore := postgres.NewPackageStore(tx) + packageSeriesStore := postgres.NewPackageSeriesStore(tx) + svc := New(packageStore, packageSeriesStore) + + ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ + UserID: 1, + UserType: constants.UserTypePlatform, + }) + + req := &dto.CreatePackageRequest{ + PackageCode: generateUniquePackageCode("PKG_STATUS"), + PackageName: "状态测试套餐", + PackageType: "formal", + DurationMonths: 1, + Price: 9900, + } + created, err := svc.Create(ctx, req) + require.NoError(t, err) + + t.Run("禁用套餐时自动强制下架", func(t *testing.T) { + err := svc.UpdateShelfStatus(ctx, created.ID, 1) + require.NoError(t, err) + + pkg, err := svc.Get(ctx, created.ID) + require.NoError(t, err) + assert.Equal(t, 1, pkg.ShelfStatus) + + err = svc.UpdateStatus(ctx, created.ID, 2) + require.NoError(t, err) + + pkg, err = svc.Get(ctx, created.ID) + require.NoError(t, err) + assert.Equal(t, 2, pkg.Status) + assert.Equal(t, 2, pkg.ShelfStatus) + }) + + t.Run("启用套餐时保持原上架状态", func(t *testing.T) { + req2 := &dto.CreatePackageRequest{ + PackageCode: generateUniquePackageCode("PKG_ENABLE"), + PackageName: "启用测试套餐", + PackageType: "formal", + DurationMonths: 1, + Price: 9900, + } + created2, err := svc.Create(ctx, req2) + require.NoError(t, err) + + err = svc.UpdateShelfStatus(ctx, created2.ID, 1) + require.NoError(t, err) + + err = svc.UpdateStatus(ctx, created2.ID, 2) + require.NoError(t, err) + + pkg, err := svc.Get(ctx, created2.ID) + require.NoError(t, err) + assert.Equal(t, 2, pkg.Status) + assert.Equal(t, 2, pkg.ShelfStatus) + + err = svc.UpdateStatus(ctx, created2.ID, 1) + require.NoError(t, err) + + pkg, err = svc.Get(ctx, created2.ID) + require.NoError(t, err) + assert.Equal(t, 1, pkg.Status) + assert.Equal(t, 2, pkg.ShelfStatus) + }) +} + +func TestPackageService_UpdateShelfStatus(t *testing.T) { + tx := testutils.NewTestTransaction(t) + packageStore := postgres.NewPackageStore(tx) + packageSeriesStore := postgres.NewPackageSeriesStore(tx) + svc := New(packageStore, packageSeriesStore) + + ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ + UserID: 1, + UserType: constants.UserTypePlatform, + }) + + t.Run("启用状态的套餐可以上架", func(t *testing.T) { + req := &dto.CreatePackageRequest{ + PackageCode: generateUniquePackageCode("PKG_SHELF_ENABLE"), + PackageName: "上架测试-启用", + PackageType: "formal", + DurationMonths: 1, + Price: 9900, + } + created, err := svc.Create(ctx, req) + require.NoError(t, err) + + pkg, err := svc.Get(ctx, created.ID) + require.NoError(t, err) + assert.Equal(t, 1, pkg.Status) + assert.Equal(t, 2, pkg.ShelfStatus) + + err = svc.UpdateShelfStatus(ctx, created.ID, 1) + require.NoError(t, err) + + pkg, err = svc.Get(ctx, created.ID) + require.NoError(t, err) + assert.Equal(t, 1, pkg.ShelfStatus) + }) + + t.Run("禁用状态的套餐不能上架", func(t *testing.T) { + req := &dto.CreatePackageRequest{ + PackageCode: generateUniquePackageCode("PKG_SHELF_DISABLE"), + PackageName: "上架测试-禁用", + PackageType: "formal", + DurationMonths: 1, + Price: 9900, + } + created, err := svc.Create(ctx, req) + require.NoError(t, err) + + err = svc.UpdateStatus(ctx, created.ID, 2) + require.NoError(t, err) + + err = svc.UpdateShelfStatus(ctx, created.ID, 1) + require.Error(t, err) + appErr, ok := err.(*errors.AppError) + require.True(t, ok) + assert.Equal(t, errors.CodeInvalidStatus, appErr.Code) + + pkg, err := svc.Get(ctx, created.ID) + require.NoError(t, err) + assert.Equal(t, 2, pkg.ShelfStatus) + }) + + t.Run("下架成功", func(t *testing.T) { + req := &dto.CreatePackageRequest{ + PackageCode: generateUniquePackageCode("PKG_SHELF_OFF"), + PackageName: "下架测试", + PackageType: "formal", + DurationMonths: 1, + Price: 9900, + } + created, err := svc.Create(ctx, req) + require.NoError(t, err) + + err = svc.UpdateShelfStatus(ctx, created.ID, 1) + require.NoError(t, err) + + pkg, err := svc.Get(ctx, created.ID) + require.NoError(t, err) + assert.Equal(t, 1, pkg.ShelfStatus) + + err = svc.UpdateShelfStatus(ctx, created.ID, 2) + require.NoError(t, err) + + pkg, err = svc.Get(ctx, created.ID) + require.NoError(t, err) + assert.Equal(t, 2, pkg.ShelfStatus) + }) +} + +func TestPackageService_Get(t *testing.T) { + tx := testutils.NewTestTransaction(t) + packageStore := postgres.NewPackageStore(tx) + packageSeriesStore := postgres.NewPackageSeriesStore(tx) + svc := New(packageStore, packageSeriesStore) + + ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ + UserID: 1, + UserType: constants.UserTypePlatform, + }) + + req := &dto.CreatePackageRequest{ + PackageCode: generateUniquePackageCode("PKG_GET"), + PackageName: "查询测试套餐", + PackageType: "formal", + DurationMonths: 1, + Price: 9900, + } + created, err := svc.Create(ctx, req) + require.NoError(t, err) + + t.Run("获取成功", func(t *testing.T) { + resp, err := svc.Get(ctx, created.ID) + require.NoError(t, err) + assert.Equal(t, created.PackageCode, resp.PackageCode) + assert.Equal(t, created.PackageName, resp.PackageName) + assert.Equal(t, created.ID, resp.ID) + }) + + t.Run("不存在返回错误", func(t *testing.T) { + _, err := svc.Get(ctx, 99999) + require.Error(t, err) + appErr, ok := err.(*errors.AppError) + require.True(t, ok) + assert.Equal(t, errors.CodeNotFound, appErr.Code) + }) +} + +func TestPackageService_List(t *testing.T) { + tx := testutils.NewTestTransaction(t) + packageStore := postgres.NewPackageStore(tx) + packageSeriesStore := postgres.NewPackageSeriesStore(tx) + svc := New(packageStore, packageSeriesStore) + + ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ + UserID: 1, + UserType: constants.UserTypePlatform, + }) + + packages := []dto.CreatePackageRequest{ + { + PackageCode: generateUniquePackageCode("PKG_LIST_001"), + PackageName: "列表测试套餐1", + PackageType: "formal", + DurationMonths: 1, + Price: 9900, + }, + { + PackageCode: generateUniquePackageCode("PKG_LIST_002"), + PackageName: "列表测试套餐2", + PackageType: "addon", + DurationMonths: 1, + Price: 4900, + }, + { + PackageCode: generateUniquePackageCode("PKG_LIST_003"), + PackageName: "列表测试套餐3", + PackageType: "formal", + DurationMonths: 12, + Price: 99900, + }, + } + + for _, p := range packages { + _, err := svc.Create(ctx, &p) + require.NoError(t, err) + } + + t.Run("列表查询", func(t *testing.T) { + req := &dto.PackageListRequest{ + Page: 1, + PageSize: 10, + } + + resp, total, err := svc.List(ctx, req) + require.NoError(t, err) + assert.Greater(t, total, int64(0)) + assert.Greater(t, len(resp), 0) + }) + + t.Run("按套餐类型过滤", func(t *testing.T) { + packageType := "formal" + req := &dto.PackageListRequest{ + Page: 1, + PageSize: 10, + PackageType: &packageType, + } + + resp, _, err := svc.List(ctx, req) + require.NoError(t, err) + for _, p := range resp { + assert.Equal(t, packageType, p.PackageType) + } + }) + + t.Run("按状态过滤", func(t *testing.T) { + status := constants.StatusEnabled + req := &dto.PackageListRequest{ + Page: 1, + PageSize: 10, + Status: &status, + } + + resp, _, err := svc.List(ctx, req) + require.NoError(t, err) + for _, p := range resp { + assert.Equal(t, status, p.Status) + } + }) +}