82 lines
3.7 KiB
Go
82 lines
3.7 KiB
Go
// 功能描述:验证结算金额确认、溢出回滚及已有订单的幂等恢复。
|
||
// 版本:1.0.0。
|
||
package user
|
||
|
||
import (
|
||
"fmt"
|
||
"math"
|
||
"strings"
|
||
"testing"
|
||
|
||
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
|
||
"github.com/DATA-DOG/go-sqlmock"
|
||
)
|
||
|
||
func TestCheckoutMoneyAndRollback(t *testing.T) {
|
||
for _, tc := range []struct {
|
||
name string
|
||
price, expected int64
|
||
code int
|
||
}{
|
||
{"数量按服务端价格结算", 12800, 25600, 0},
|
||
{"价格变化回滚库存", 12800, 12800, 2401},
|
||
{"金额溢出不扣库存", math.MaxInt64, 0, 1711},
|
||
} {
|
||
t.Run(tc.name, func(t *testing.T) {
|
||
mock := primaryTestDB(t)
|
||
expectAddressAccount(mock)
|
||
mock.ExpectQuery(`SELECT .* FROM "ec_order"`).WillReturnRows(sqlmock.NewRows([]string{"id"}))
|
||
mock.ExpectQuery(`SELECT .* FROM "user_address"`).WillReturnRows(sqlmock.NewRows([]string{"id", "identity", "address"}).AddRow(2, "owned", "测试地址"))
|
||
mock.ExpectBegin()
|
||
mock.ExpectQuery(`SELECT .* FROM "ec_product".*FOR UPDATE`).WillReturnRows(sqlmock.NewRows([]string{"id", "identity", "price_amount", "stock_quantity"}).AddRow(3, "product", tc.price, 20))
|
||
if tc.code != 1711 {
|
||
mock.ExpectExec(`UPDATE "ec_product" SET "stock_quantity"`).WillReturnResult(sqlmock.NewResult(0, 1))
|
||
mock.ExpectQuery(`SELECT .* FROM "ec_product_image"`).
|
||
WillReturnRows(sqlmock.NewRows([]string{"id", "image_uri"}).AddRow(8, "/uploads/products/cover.png"))
|
||
}
|
||
if tc.code == 0 {
|
||
mock.ExpectQuery(`INSERT INTO "ec_order"`).WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(5))
|
||
mock.ExpectQuery(`INSERT INTO "ec_order_item"`).WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(6))
|
||
mock.ExpectCommit()
|
||
} else {
|
||
mock.ExpectRollback()
|
||
mock.ExpectQuery(`SELECT .* FROM "ec_order"`).WillReturnRows(sqlmock.NewRows([]string{"id"}))
|
||
}
|
||
ctx, response := addressContext(fmt.Sprintf(`{"request_no":"order-request","address_identity":"owned","contact_name":"收货人","contact_phone":"13800000001","expected_payable_amount":%d,"items":[{"product_identity":"product","quantity":2}]}`, tc.expected), "")
|
||
CreateShopOrder(ctx)
|
||
if !strings.Contains(response.Body.String(), fmt.Sprintf(`"code":%d`, tc.code)) {
|
||
t.Fatal(response.Body.String())
|
||
}
|
||
if tc.code == 0 && !strings.Contains(response.Body.String(), `"payable_amount":25600`) {
|
||
t.Fatal("未按数量返回总额")
|
||
}
|
||
if err := mock.ExpectationsWereMet(); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
func TestShopOrderProductSnapshotIncludesCover(t *testing.T) {
|
||
value := shopOrderProductSnapshot(models.EcProduct{Entity: models.Entity{Identity: "product"}, Name: "报警器", ProductCode: "BJQ-01"}, "/uploads/products/cover.png")
|
||
for _, expected := range []string{`"identity":"product"`, `"name":"报警器"`, `"product_code":"BJQ-01"`, `"image_url":"/uploads/products/cover.png"`} {
|
||
if !strings.Contains(value, expected) {
|
||
t.Fatalf("订单商品快照缺少 %s: %s", expected, value)
|
||
}
|
||
}
|
||
}
|
||
|
||
func TestCheckoutRetrySurvivesAddressRemoval(t *testing.T) {
|
||
mock := primaryTestDB(t)
|
||
expectAddressAccount(mock)
|
||
mock.ExpectQuery(`SELECT .* FROM "ec_order".*request_no = \$1 AND user_account_id = \$2`).WillReturnRows(sqlmock.NewRows([]string{"id", "identity", "payable_amount"}).AddRow(5, "existing-order", 25600))
|
||
ctx, response := addressContext(`{"request_no":"order-request","address_identity":"removed","contact_name":"收货人","contact_phone":"13800000001","items":[{"product_identity":"product","quantity":2}]}`, "")
|
||
CreateShopOrder(ctx)
|
||
if !strings.Contains(response.Body.String(), `"identity":"existing-order"`) {
|
||
t.Fatal(response.Body.String())
|
||
}
|
||
if err := mock.ExpectationsWereMet(); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
}
|