本次提交同时完成碎片批量合成与盒柜发货运费规则改造,减少用户重复操作,并确保不包邮商品在任何件数下都必须支付运费。 - 合成功能:新增批量合成接口与前端一键合成入口,按配方可合成上限批量消耗碎片并生成对应资产,同时补充批量合成测试 - 运费规则:后端新增统一运费判定逻辑,命中 category_id 14/15 的商品时整单强制收取运费,否则继续沿用少于 5 件收运费的旧规则 - 发货流程:新增运费检查接口,前端发货前先向后端确认是否需要支付运费,并根据“件数不足”或“包含不包邮商品”展示不同提示文案 - 接口校验:运费预下单与批量申请发货统一复用后端判定逻辑,避免前端规则被绕过
137 lines
4.1 KiB
Go
Executable File
137 lines
4.1 KiB
Go
Executable File
package user
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/DATA-DOG/go-sqlmock"
|
|
"github.com/stretchr/testify/assert"
|
|
"gorm.io/driver/mysql"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
func setupMockDBForShipping(t *testing.T) (*gorm.DB, sqlmock.Sqlmock) {
|
|
db, mock, err := sqlmock.New()
|
|
if err != nil {
|
|
t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
|
|
}
|
|
gormDB, err := gorm.Open(mysql.New(mysql.Config{
|
|
Conn: db,
|
|
SkipInitializeWithVersion: true,
|
|
}), &gorm.Config{})
|
|
if err != nil {
|
|
t.Fatalf("an error '%s' was not expected when opening gorm database", err)
|
|
}
|
|
return gormDB, mock
|
|
}
|
|
|
|
func TestRequestShippings_EmptyInventoryIDs(t *testing.T) {
|
|
db, _ := setupMockDBForShipping(t)
|
|
svc := newTestService(db)
|
|
|
|
_, _, _, _, failed, err := svc.RequestShippings(context.Background(), 1, []int64{}, nil)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, failed, 1)
|
|
assert.Equal(t, "invalid_params", failed[0].Reason)
|
|
}
|
|
|
|
func TestRequestShippings_AllZeroInventoryIDs(t *testing.T) {
|
|
db, _ := setupMockDBForShipping(t)
|
|
svc := newTestService(db)
|
|
|
|
_, _, _, _, failed, err := svc.RequestShippings(context.Background(), 1, []int64{0, -1, 0}, nil)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, failed, 1)
|
|
assert.Equal(t, "invalid_params", failed[0].Reason)
|
|
}
|
|
|
|
func TestRequestShippings_NoDefaultAddress(t *testing.T) {
|
|
db, mock := setupMockDBForShipping(t)
|
|
svc := newTestService(db)
|
|
|
|
mock.ExpectQuery("SELECT .* FROM `user_addresses`").
|
|
WillReturnRows(sqlmock.NewRows(nil))
|
|
mock.ExpectQuery("SELECT .* FROM `user_addresses`").
|
|
WillReturnRows(sqlmock.NewRows(nil))
|
|
|
|
_, _, _, _, failed, err := svc.RequestShippings(context.Background(), 1, []int64{1, 2}, nil)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, failed, 1)
|
|
assert.Equal(t, "no_default_address", failed[0].Reason)
|
|
}
|
|
|
|
func TestCheckShippingFeeRequirement_BelowThreshold(t *testing.T) {
|
|
db, mock := setupMockDBForShipping(t)
|
|
svc := newTestService(db)
|
|
|
|
mock.ExpectQuery("SELECT .* FROM `user_inventory`").
|
|
WillReturnRows(sqlmock.NewRows([]string{"id", "user_id", "product_id"}).
|
|
AddRow(1, 99, 101).
|
|
AddRow(2, 99, 102).
|
|
AddRow(3, 99, 103).
|
|
AddRow(4, 99, 104))
|
|
mock.ExpectQuery("SELECT .* FROM `products`").
|
|
WillReturnRows(sqlmock.NewRows([]string{"id", "category_id"}).
|
|
AddRow(101, 1).
|
|
AddRow(102, 2).
|
|
AddRow(103, 3).
|
|
AddRow(104, 4))
|
|
|
|
needFee, reason, err := svc.CheckShippingFeeRequirement(context.Background(), 99, []int64{1, 2, 3, 4})
|
|
assert.NoError(t, err)
|
|
assert.True(t, needFee)
|
|
assert.Equal(t, shippingFeeReasonBelowThreshold, reason)
|
|
}
|
|
|
|
func TestCheckShippingFeeRequirement_FreeWhenThresholdReached(t *testing.T) {
|
|
db, mock := setupMockDBForShipping(t)
|
|
svc := newTestService(db)
|
|
|
|
mock.ExpectQuery("SELECT .* FROM `user_inventory`").
|
|
WillReturnRows(sqlmock.NewRows([]string{"id", "user_id", "product_id"}).
|
|
AddRow(1, 99, 101).
|
|
AddRow(2, 99, 102).
|
|
AddRow(3, 99, 103).
|
|
AddRow(4, 99, 104).
|
|
AddRow(5, 99, 105))
|
|
mock.ExpectQuery("SELECT .* FROM `products`").
|
|
WillReturnRows(sqlmock.NewRows([]string{"id", "category_id"}).
|
|
AddRow(101, 1).
|
|
AddRow(102, 2).
|
|
AddRow(103, 3).
|
|
AddRow(104, 4).
|
|
AddRow(105, 5))
|
|
|
|
needFee, reason, err := svc.CheckShippingFeeRequirement(context.Background(), 99, []int64{1, 2, 3, 4, 5})
|
|
assert.NoError(t, err)
|
|
assert.False(t, needFee)
|
|
assert.Equal(t, "", reason)
|
|
}
|
|
|
|
func TestCheckShippingFeeRequirement_NonFreeCategoryOverridesThreshold(t *testing.T) {
|
|
db, mock := setupMockDBForShipping(t)
|
|
svc := newTestService(db)
|
|
|
|
mock.ExpectQuery("SELECT .* FROM `user_inventory`").
|
|
WillReturnRows(sqlmock.NewRows([]string{"id", "user_id", "product_id"}).
|
|
AddRow(1, 99, 101).
|
|
AddRow(2, 99, 102).
|
|
AddRow(3, 99, 103).
|
|
AddRow(4, 99, 104).
|
|
AddRow(5, 99, 105).
|
|
AddRow(6, 99, 106))
|
|
mock.ExpectQuery("SELECT .* FROM `products`").
|
|
WillReturnRows(sqlmock.NewRows([]string{"id", "category_id"}).
|
|
AddRow(101, 1).
|
|
AddRow(102, 2).
|
|
AddRow(103, 3).
|
|
AddRow(104, 4).
|
|
AddRow(105, 14).
|
|
AddRow(106, 5))
|
|
|
|
needFee, reason, err := svc.CheckShippingFeeRequirement(context.Background(), 99, []int64{1, 2, 3, 4, 5, 6})
|
|
assert.NoError(t, err)
|
|
assert.True(t, needFee)
|
|
assert.Equal(t, shippingFeeReasonContainsNonFreeShipping, reason)
|
|
}
|