createProductLogic_test.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. package product
  2. import (
  3. "errors"
  4. "sync"
  5. "testing"
  6. productModel "perms-system-server/internal/model/product"
  7. "perms-system-server/internal/response"
  8. "perms-system-server/internal/svc"
  9. "perms-system-server/internal/testutil"
  10. "perms-system-server/internal/testutil/ctxhelper"
  11. "perms-system-server/internal/types"
  12. "github.com/stretchr/testify/assert"
  13. "github.com/stretchr/testify/require"
  14. )
  15. // TC-0060: 正常创建
  16. func TestCreateProduct_Success(t *testing.T) {
  17. ctx := ctxhelper.SuperAdminCtx()
  18. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  19. conn := testutil.GetTestSqlConn()
  20. code := testutil.UniqueId()
  21. logic := NewCreateProductLogic(ctx, svcCtx)
  22. resp, err := logic.CreateProduct(&types.CreateProductReq{
  23. Code: code,
  24. Name: "测试产品",
  25. Remark: "集成测试",
  26. })
  27. require.NoError(t, err)
  28. require.NotNil(t, resp)
  29. t.Cleanup(func() {
  30. testutil.CleanTableByField(ctx, conn, "`sys_product_member`", "productCode", code)
  31. testutil.CleanTableByField(ctx, conn, "`sys_user`", "username", "admin_"+code)
  32. testutil.CleanTable(ctx, conn, "`sys_product`", resp.Id)
  33. })
  34. assert.True(t, resp.Id > 0)
  35. assert.Equal(t, code, resp.Code)
  36. assert.NotEmpty(t, resp.AppKey)
  37. assert.NotEmpty(t, resp.AppSecret)
  38. assert.Equal(t, "admin_"+code, resp.AdminUser)
  39. assert.NotEmpty(t, resp.AdminPassword)
  40. }
  41. // TC-0060: 正常创建
  42. func TestCreateProduct_VerifyDB(t *testing.T) {
  43. ctx := ctxhelper.SuperAdminCtx()
  44. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  45. conn := testutil.GetTestSqlConn()
  46. code := testutil.UniqueId()
  47. logic := NewCreateProductLogic(ctx, svcCtx)
  48. resp, err := logic.CreateProduct(&types.CreateProductReq{
  49. Code: code,
  50. Name: "DB验证产品",
  51. Remark: "验证数据库记录",
  52. })
  53. require.NoError(t, err)
  54. t.Cleanup(func() {
  55. testutil.CleanTableByField(ctx, conn, "`sys_product_member`", "productCode", code)
  56. testutil.CleanTableByField(ctx, conn, "`sys_user`", "username", "admin_"+code)
  57. testutil.CleanTable(ctx, conn, "`sys_product`", resp.Id)
  58. })
  59. product, err := svcCtx.SysProductModel.FindOne(ctx, resp.Id)
  60. require.NoError(t, err)
  61. assert.Equal(t, code, product.Code)
  62. assert.Equal(t, "DB验证产品", product.Name)
  63. assert.Equal(t, resp.AppKey, product.AppKey)
  64. assert.Equal(t, resp.AppSecret, product.AppSecret)
  65. assert.Equal(t, int64(1), product.Status)
  66. var userCount int64
  67. err = conn.QueryRowCtx(ctx, &userCount,
  68. "SELECT COUNT(*) FROM `sys_user` WHERE `username` = ?", "admin_"+code)
  69. require.NoError(t, err)
  70. assert.Equal(t, int64(1), userCount)
  71. var memberCount int64
  72. err = conn.QueryRowCtx(ctx, &memberCount,
  73. "SELECT COUNT(*) FROM `sys_product_member` WHERE `productCode` = ? AND `memberType` = 'ADMIN'", code)
  74. require.NoError(t, err)
  75. assert.Equal(t, int64(1), memberCount)
  76. }
  77. // TC-0063: 编码已存在
  78. func TestCreateProduct_DuplicateCode(t *testing.T) {
  79. ctx := ctxhelper.SuperAdminCtx()
  80. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  81. conn := testutil.GetTestSqlConn()
  82. code := testutil.UniqueId()
  83. logic := NewCreateProductLogic(ctx, svcCtx)
  84. resp, err := logic.CreateProduct(&types.CreateProductReq{
  85. Code: code,
  86. Name: "第一个产品",
  87. })
  88. require.NoError(t, err)
  89. t.Cleanup(func() {
  90. testutil.CleanTableByField(ctx, conn, "`sys_product_member`", "productCode", code)
  91. testutil.CleanTableByField(ctx, conn, "`sys_user`", "username", "admin_"+code)
  92. testutil.CleanTable(ctx, conn, "`sys_product`", resp.Id)
  93. })
  94. logic2 := NewCreateProductLogic(ctx, svcCtx)
  95. _, err = logic2.CreateProduct(&types.CreateProductReq{
  96. Code: code,
  97. Name: "重复产品",
  98. })
  99. require.Error(t, err)
  100. var codeErr *response.CodeError
  101. require.True(t, errors.As(err, &codeErr))
  102. assert.Equal(t, 409, codeErr.Code())
  103. assert.Equal(t, "产品编码已存在", codeErr.Error())
  104. }
  105. // TC-0064: 并发创建同编码
  106. func TestCreateProduct_ConcurrentSameCode(t *testing.T) {
  107. ctx := ctxhelper.SuperAdminCtx()
  108. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  109. conn := testutil.GetTestSqlConn()
  110. code := testutil.UniqueId()
  111. t.Cleanup(func() {
  112. testutil.CleanTableByField(ctx, conn, "`sys_product_member`", "productCode", code)
  113. testutil.CleanTableByField(ctx, conn, "`sys_user`", "username", "admin_"+code)
  114. testutil.CleanTableByField(ctx, conn, "`sys_product`", "code", code)
  115. })
  116. var wg sync.WaitGroup
  117. results := make(chan error, 2)
  118. for i := 0; i < 2; i++ {
  119. wg.Add(1)
  120. go func() {
  121. defer wg.Done()
  122. logic := NewCreateProductLogic(ctx, svcCtx)
  123. _, err := logic.CreateProduct(&types.CreateProductReq{
  124. Code: code,
  125. Name: "并发测试产品",
  126. })
  127. results <- err
  128. }()
  129. }
  130. wg.Wait()
  131. close(results)
  132. var errs []error
  133. for err := range results {
  134. errs = append(errs, err)
  135. }
  136. require.Len(t, errs, 2)
  137. successCount := 0
  138. failCount := 0
  139. for _, err := range errs {
  140. if err == nil {
  141. successCount++
  142. } else {
  143. failCount++
  144. }
  145. }
  146. assert.Equal(t, 1, successCount, "exactly one goroutine should succeed")
  147. assert.Equal(t, 1, failCount, "exactly one goroutine should fail (409 or DB duplicate)")
  148. }
  149. // TC-0514: createProduct非超管拒绝
  150. func TestCreateProduct_NonSuperAdminRejected(t *testing.T) {
  151. ctx := ctxhelper.AdminCtx("test_product")
  152. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  153. logic := NewCreateProductLogic(ctx, svcCtx)
  154. _, err := logic.CreateProduct(&types.CreateProductReq{Code: "test", Name: "test"})
  155. require.Error(t, err)
  156. var ce *response.CodeError
  157. require.True(t, errors.As(err, &ce))
  158. assert.Equal(t, 403, ce.Code())
  159. }
  160. // suppress unused import
  161. var _ = (*productModel.SysProduct)(nil)