已完成用户APP首期功能开发
交付用户端首期页面、配套接口、后台资源及测试文档。用户APP构建、静态分析和三个管理后台构建通过;完整测试仍有2项失败,后端模型注释检查未通过,详见交付记录。
This commit is contained in:
81
backend/api/internal/logic/client/user/checkout_test.go
Normal file
81
backend/api/internal/logic/client/user/checkout_test.go
Normal file
@@ -0,0 +1,81 @@
|
||||
// 功能描述:验证结算金额确认、溢出回滚及已有订单的幂等恢复。
|
||||
// 版本: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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user