feature/order_base #1
|
@ -1,19 +1,13 @@
|
|||
use digimon_order;
|
||||
|
||||
db.order.createIndex({ "business_id": 1, "order_status": 1, "create_time": -1 })
|
||||
db.orders.createIndex({ "reference_id": 1, "reference_uid": 1, "business_id": 1, "uid": 1 })
|
||||
db.orders.createIndex({ "order_type": 1, "direction_type": 1, "order_status": 1 })
|
||||
db.orders.createIndex({ "create_time": -1, "update_time": -1, "order_arrival_time": -1, "order_payment_time": -1 })
|
||||
|
||||
db.order.createIndex({
|
||||
"uid": 1,
|
||||
"order_type": 1,
|
||||
"order_status": 1,
|
||||
"create_time": 1,
|
||||
})
|
||||
|
||||
db.order.createIndex({
|
||||
"business_id": 1,
|
||||
})
|
||||
|
||||
// 查詢時全部要 1&2 有幾個類用幾個累才會中索引
|
||||
db.order.createIndex({
|
||||
"uid": 1,
|
||||
"direction_type": 1,
|
||||
"crypto_type": 1
|
||||
"create_time": -1,
|
||||
})
|
|
@ -152,8 +152,6 @@ service OrderService {
|
|||
rpc CreateOrder(CreateOrderReq) returns (OKResp);
|
||||
// CancelOrder 取消訂單
|
||||
rpc CancelOrder(CancelOrderReq) returns (OKResp);
|
||||
// ModifyOrder 修改訂單
|
||||
rpc ModifyOrder(ModifyOrderReq) returns (OKResp);
|
||||
// ModifyOrderStatus 修改訂單狀態
|
||||
rpc ModifyOrderStatus(ModifyOrderStatusReq) returns (OKResp);
|
||||
// DeleteOrder 刪除訂單(軟刪除)
|
||||
|
|
4
go.mod
4
go.mod
|
@ -5,7 +5,9 @@ go 1.22.3
|
|||
require (
|
||||
code.30cm.net/digimon/library-go/errs v1.2.5
|
||||
code.30cm.net/digimon/library-go/validator v1.0.0
|
||||
github.com/go-playground/validator/v10 v10.22.0
|
||||
github.com/shopspring/decimal v1.4.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/zeromicro/go-zero v1.7.2
|
||||
go.mongodb.org/mongo-driver v1.16.1
|
||||
go.uber.org/mock v0.4.0
|
||||
|
@ -31,7 +33,6 @@ require (
|
|||
github.com/go-openapi/swag v0.22.4 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.22.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
|
@ -54,6 +55,7 @@ require (
|
|||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/openzipkin/zipkin-go v0.4.3 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_golang v1.20.2 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.55.0 // indirect
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
package orderservicelogic
|
||||
|
||||
import (
|
||||
"app-cloudep-order-server/gen_result/pb/order"
|
||||
mocksvc "app-cloudep-order-server/internal/mock/lib"
|
||||
model "app-cloudep-order-server/internal/model/mongo"
|
||||
"app-cloudep-order-server/internal/svc"
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.uber.org/mock/gomock"
|
||||
"testing"
|
||||
|
||||
mockmodel "app-cloudep-order-server/internal/mock/model"
|
||||
)
|
||||
|
||||
func TestCancelOrder(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
// 初始化 mock 依賴
|
||||
mockOrderModel := mockmodel.NewMockOrderModel(ctrl)
|
||||
mockValidate := mocksvc.NewMockValidate(ctrl)
|
||||
|
||||
// 初始化服務上下文
|
||||
svcCtx := &svc.ServiceContext{
|
||||
OrderModel: mockOrderModel,
|
||||
Validate: mockValidate,
|
||||
}
|
||||
|
||||
// 測試數據
|
||||
cancelReq := &order.CancelOrderReq{
|
||||
BusinessId: "12345",
|
||||
Status: 1,
|
||||
}
|
||||
|
||||
// 測試數據集
|
||||
tests := []struct {
|
||||
name string
|
||||
input *order.CancelOrderReq
|
||||
prepare func()
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
name: "成功取消訂單",
|
||||
input: cancelReq,
|
||||
prepare: func() {
|
||||
// 模擬驗證通過
|
||||
mockValidate.EXPECT().ValidateAll(gomock.Any()).Return(nil).Times(1)
|
||||
// 模擬更新狀態成功
|
||||
mockOrderModel.EXPECT().UpdateStatus(gomock.Any(), model.UpdateStatusReq{
|
||||
BusinessID: "12345",
|
||||
Status: 1,
|
||||
}).Return(&mongo.UpdateResult{MatchedCount: 1}, nil).Times(1)
|
||||
},
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "訂單更新狀態失敗",
|
||||
input: cancelReq,
|
||||
prepare: func() {
|
||||
// 模擬驗證通過
|
||||
mockValidate.EXPECT().ValidateAll(gomock.Any()).Return(nil).Times(1)
|
||||
// 模擬更新狀態失敗
|
||||
mockOrderModel.EXPECT().UpdateStatus(gomock.Any(), model.UpdateStatusReq{
|
||||
BusinessID: "12345",
|
||||
Status: 1,
|
||||
}).Return(nil, errors.New("update failed")).Times(1)
|
||||
},
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "驗證失敗",
|
||||
input: cancelReq,
|
||||
prepare: func() {
|
||||
// 模擬驗證失敗
|
||||
mockValidate.EXPECT().ValidateAll(gomock.Any()).Return(errors.New("invalid input")).Times(1)
|
||||
},
|
||||
expectErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
// 執行測試
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// 設置測試環境
|
||||
tt.prepare()
|
||||
|
||||
// 初始化 CancelOrderLogic
|
||||
logic := CancelOrderLogic{
|
||||
svcCtx: svcCtx,
|
||||
ctx: context.TODO(),
|
||||
}
|
||||
|
||||
// 執行 CancelOrder
|
||||
resp, err := logic.CancelOrder(tt.input)
|
||||
|
||||
// 驗證結果
|
||||
if tt.expectErr {
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, resp)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,406 @@
|
|||
package orderservicelogic
|
||||
|
||||
import (
|
||||
"app-cloudep-order-server/gen_result/pb/order"
|
||||
mocksvc "app-cloudep-order-server/internal/mock/lib"
|
||||
mockmodel "app-cloudep-order-server/internal/mock/model"
|
||||
"app-cloudep-order-server/internal/svc"
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/shopspring/decimal"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.uber.org/mock/gomock"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestDecimalPtrFromString(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
expected *decimal.Decimal
|
||||
}{
|
||||
{
|
||||
name: "valid decimal string",
|
||||
input: "10.5",
|
||||
expected: decimalPtr("10.5"), // 使用輔助函數將字串轉換為指針
|
||||
},
|
||||
{
|
||||
name: "empty string returns nil",
|
||||
input: "",
|
||||
expected: nil,
|
||||
},
|
||||
{
|
||||
name: "invalid decimal string returns nil",
|
||||
input: "invalid-decimal",
|
||||
expected: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := decimalPtrFromString(tt.input) // 調用要測試的函數
|
||||
if tt.expected == nil {
|
||||
assert.Nil(t, result)
|
||||
} else {
|
||||
assert.NotNil(t, result)
|
||||
assert.True(t, tt.expected.Equal(*result), "Expected %v, got %v", tt.expected, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildCreateOrderReq(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input *order.CreateOrderReq
|
||||
expectErr bool
|
||||
expected *createOrderReq
|
||||
}{
|
||||
{
|
||||
name: "所有必填字段存在,可選字段為空",
|
||||
input: &order.CreateOrderReq{
|
||||
BusinessId: "B123",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUid: "UID123",
|
||||
ReferenceId: "REF123",
|
||||
Count: "10.5",
|
||||
OrderFee: "0.5",
|
||||
Amount: "100",
|
||||
},
|
||||
expectErr: false,
|
||||
expected: &createOrderReq{
|
||||
BusinessID: "B123",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUID: "UID123",
|
||||
ReferenceID: "REF123",
|
||||
Count: decimal.RequireFromString("10.5"),
|
||||
OrderFee: decimal.RequireFromString("0.5"),
|
||||
Amount: decimal.RequireFromString("100"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "包含可選字段",
|
||||
input: &order.CreateOrderReq{
|
||||
BusinessId: "B123",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUid: "UID123",
|
||||
ReferenceId: "REF123",
|
||||
Count: "10.5",
|
||||
OrderFee: "0.5",
|
||||
Amount: "100",
|
||||
ReferenceBrand: ptr("OtherBrand"),
|
||||
WalletStatus: ptrInt64(1),
|
||||
ThreePartyStatus: ptrInt64(2),
|
||||
},
|
||||
expectErr: false,
|
||||
expected: &createOrderReq{
|
||||
BusinessID: "B123",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUID: "UID123",
|
||||
ReferenceID: "REF123",
|
||||
Count: decimal.RequireFromString("10.5"),
|
||||
OrderFee: decimal.RequireFromString("0.5"),
|
||||
Amount: decimal.RequireFromString("100"),
|
||||
ReferenceBrand: ptr("OtherBrand"),
|
||||
WalletStatus: ptrInt64(1),
|
||||
ThreePartyStatus: ptrInt64(2),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "無效的十進制字段",
|
||||
input: &order.CreateOrderReq{
|
||||
BusinessId: "B123",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUid: "UID123",
|
||||
ReferenceId: "REF123",
|
||||
Count: "invalid-decimal", // 無效的數值
|
||||
},
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "空字符串的可選欄位應返回 nil",
|
||||
input: &order.CreateOrderReq{
|
||||
BusinessId: "B123",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUid: "UID123",
|
||||
ReferenceId: "REF123",
|
||||
Count: "10.5",
|
||||
OrderFee: "0.5",
|
||||
Amount: "100",
|
||||
ThirdPartyFee: ptr(""), // 空字符串
|
||||
},
|
||||
expectErr: false,
|
||||
expected: &createOrderReq{
|
||||
BusinessID: "B123",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUID: "UID123",
|
||||
ReferenceID: "REF123",
|
||||
Count: decimal.RequireFromString("10.5"),
|
||||
OrderFee: decimal.RequireFromString("0.5"),
|
||||
Amount: decimal.RequireFromString("100"),
|
||||
ThirdPartyFee: nil, // 空字符串應返回 nil
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := buildCreateOrderReq(tt.input)
|
||||
if tt.expectErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.expected, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateOrder(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
// 初始化 mock 依賴
|
||||
mockOrderModel := mockmodel.NewMockOrderModel(ctrl)
|
||||
mockValidate := mocksvc.NewMockValidate(ctrl)
|
||||
|
||||
// 初始化服務上下文
|
||||
svcCtx := &svc.ServiceContext{
|
||||
OrderModel: mockOrderModel,
|
||||
Validate: mockValidate,
|
||||
}
|
||||
|
||||
// 測試數據集
|
||||
tests := []struct {
|
||||
name string
|
||||
input *order.CreateOrderReq
|
||||
prepare func()
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
name: "成功建立訂單",
|
||||
input: &order.CreateOrderReq{
|
||||
BusinessId: "B123",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUid: "UID123",
|
||||
ReferenceId: "REF123",
|
||||
Count: "10.5",
|
||||
OrderFee: "0.5",
|
||||
Amount: "100",
|
||||
},
|
||||
prepare: func() {
|
||||
// 模擬驗證成功
|
||||
mockValidate.EXPECT().ValidateAll(gomock.Any()).Return(nil).Times(1)
|
||||
// 模擬資料庫插入成功
|
||||
mockOrderModel.EXPECT().Insert(gomock.Any(), gomock.Any()).Return(nil).Times(1)
|
||||
},
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "建立訂單時驗證失敗",
|
||||
input: &order.CreateOrderReq{
|
||||
BusinessId: "B123",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUid: "UID123",
|
||||
ReferenceId: "REF123",
|
||||
Count: "10.5",
|
||||
OrderFee: "0.5",
|
||||
Amount: "100",
|
||||
},
|
||||
prepare: func() {
|
||||
// 模擬驗證失敗
|
||||
mockValidate.EXPECT().ValidateAll(gomock.Any()).Return(errors.New("validation failed")).Times(1)
|
||||
},
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "插入資料庫失敗",
|
||||
input: &order.CreateOrderReq{
|
||||
BusinessId: "B123",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUid: "UID123",
|
||||
ReferenceId: "REF123",
|
||||
Count: "10.5",
|
||||
OrderFee: "0.5",
|
||||
Amount: "100",
|
||||
},
|
||||
prepare: func() {
|
||||
// 模擬驗證成功
|
||||
mockValidate.EXPECT().ValidateAll(gomock.Any()).Return(nil).Times(1)
|
||||
// 模擬插入資料庫失敗
|
||||
mockOrderModel.EXPECT().Insert(gomock.Any(), gomock.Any()).Return(errors.New("insert failed")).Times(1)
|
||||
},
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "成功建立訂單,必填字段",
|
||||
input: &order.CreateOrderReq{
|
||||
BusinessId: "B123",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUid: "UID123",
|
||||
ReferenceId: "REF123",
|
||||
Count: "10.5",
|
||||
OrderFee: "0.5",
|
||||
Amount: "100",
|
||||
},
|
||||
prepare: func() {
|
||||
// 模擬驗證成功
|
||||
mockValidate.EXPECT().ValidateAll(gomock.Any()).Return(nil).Times(1)
|
||||
// 模擬資料庫插入成功
|
||||
mockOrderModel.EXPECT().Insert(gomock.Any(), gomock.Any()).Return(nil).Times(1)
|
||||
},
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "成功建立訂單,可選字段有值",
|
||||
input: &order.CreateOrderReq{
|
||||
BusinessId: "B123",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUid: "UID123",
|
||||
ReferenceId: "REF123",
|
||||
Count: "10.5",
|
||||
OrderFee: "0.5",
|
||||
Amount: "100",
|
||||
ReferenceBrand: ptr("OtherBrand"),
|
||||
WalletStatus: ptrInt64(1),
|
||||
CryptoType: ptr("BTC"),
|
||||
PaymentFiat: ptr("USD"),
|
||||
OrderArrivalTime: ptrInt64(time.Now().UTC().Unix()),
|
||||
},
|
||||
prepare: func() {
|
||||
// 模擬驗證成功
|
||||
mockValidate.EXPECT().ValidateAll(gomock.Any()).Return(nil).Times(1)
|
||||
// 模擬資料庫插入成功
|
||||
mockOrderModel.EXPECT().Insert(gomock.Any(), gomock.Any()).Return(nil).Times(1)
|
||||
},
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "部分可選字段有值,其他為空",
|
||||
input: &order.CreateOrderReq{
|
||||
BusinessId: "B123",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUid: "UID123",
|
||||
ReferenceId: "REF123",
|
||||
Count: "10.5",
|
||||
OrderFee: "0.5",
|
||||
Amount: "100",
|
||||
ReferenceBrand: ptr("OtherBrand"),
|
||||
WalletStatus: ptrInt64(1),
|
||||
CryptoType: nil, // 空
|
||||
PaymentFiat: nil, // 空
|
||||
},
|
||||
prepare: func() {
|
||||
// 模擬驗證成功
|
||||
mockValidate.EXPECT().ValidateAll(gomock.Any()).Return(nil).Times(1)
|
||||
// 模擬資料庫插入成功
|
||||
mockOrderModel.EXPECT().Insert(gomock.Any(), gomock.Any()).Return(nil).Times(1)
|
||||
},
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "無效的十進制數字",
|
||||
input: &order.CreateOrderReq{
|
||||
BusinessId: "B123",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUid: "UID123",
|
||||
ReferenceId: "REF123",
|
||||
Count: "invalid", // 無效的數值
|
||||
OrderFee: "0.5",
|
||||
Amount: "100",
|
||||
},
|
||||
prepare: func() {
|
||||
// 無需調用資料庫操作,因為會在驗證或轉換時失敗
|
||||
},
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "可選欄位為空字符串",
|
||||
input: &order.CreateOrderReq{
|
||||
BusinessId: "B123",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUid: "UID123",
|
||||
ReferenceId: "REF123",
|
||||
Count: "10.5",
|
||||
OrderFee: "0.5",
|
||||
Amount: "100",
|
||||
ThirdPartyFee: ptr(""), // 空字符串
|
||||
},
|
||||
prepare: func() {
|
||||
// 模擬驗證成功
|
||||
mockValidate.EXPECT().ValidateAll(gomock.Any()).Return(nil).Times(1)
|
||||
// 模擬資料庫插入成功
|
||||
mockOrderModel.EXPECT().Insert(gomock.Any(), gomock.Any()).Return(nil).Times(1)
|
||||
},
|
||||
expectErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// 設置測試環境
|
||||
tt.prepare()
|
||||
|
||||
// 初始化 CreateOrderLogic
|
||||
logic := NewCreateOrderLogic(context.TODO(), svcCtx)
|
||||
|
||||
// 執行 CreateOrder
|
||||
resp, err := logic.CreateOrder(tt.input)
|
||||
|
||||
// 驗證結果
|
||||
if tt.expectErr {
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, resp)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// ================================ 輔助函數 ================================
|
||||
func ptr(s string) *string {
|
||||
return &s
|
||||
}
|
||||
|
||||
func ptrInt64(i int64) *int64 {
|
||||
return &i
|
||||
}
|
||||
|
||||
// decimalPtr 是一個輔助函數,用來將字串轉換為 *decimal.Decimal 指針
|
||||
func decimalPtr(val string) *decimal.Decimal {
|
||||
d, _ := decimal.NewFromString(val)
|
||||
return &d
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
package orderservicelogic
|
||||
|
||||
import (
|
||||
"app-cloudep-order-server/gen_result/pb/order"
|
||||
mocksvc "app-cloudep-order-server/internal/mock/lib"
|
||||
mockmodel "app-cloudep-order-server/internal/mock/model"
|
||||
"app-cloudep-order-server/internal/svc"
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.uber.org/mock/gomock"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDeleteOrder(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
// 初始化 mock 依賴
|
||||
mockOrderModel := mockmodel.NewMockOrderModel(ctrl)
|
||||
mockValidate := mocksvc.NewMockValidate(ctrl)
|
||||
|
||||
// 初始化服務上下文
|
||||
svcCtx := &svc.ServiceContext{
|
||||
OrderModel: mockOrderModel,
|
||||
Validate: mockValidate,
|
||||
}
|
||||
|
||||
// 測試數據集
|
||||
tests := []struct {
|
||||
name string
|
||||
input *order.DeleteOrderReq
|
||||
prepare func()
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
name: "成功刪除訂單",
|
||||
input: &order.DeleteOrderReq{
|
||||
BusinessId: "B123",
|
||||
},
|
||||
prepare: func() {
|
||||
// 模擬驗證成功
|
||||
mockValidate.EXPECT().ValidateAll(gomock.Any()).Return(nil).Times(1)
|
||||
// 模擬資料庫刪除成功
|
||||
mockOrderModel.EXPECT().DeleteByBusinessID(gomock.Any(), "B123").Return(nil, nil).Times(1)
|
||||
},
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "驗證失敗",
|
||||
input: &order.DeleteOrderReq{
|
||||
BusinessId: "B123",
|
||||
},
|
||||
prepare: func() {
|
||||
// 模擬驗證失敗
|
||||
mockValidate.EXPECT().ValidateAll(gomock.Any()).Return(errors.New("validation failed")).Times(1)
|
||||
},
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "刪除資料庫失敗",
|
||||
input: &order.DeleteOrderReq{
|
||||
BusinessId: "B123",
|
||||
},
|
||||
prepare: func() {
|
||||
// 模擬驗證成功
|
||||
mockValidate.EXPECT().ValidateAll(gomock.Any()).Return(nil).Times(1)
|
||||
// 模擬資料庫刪除失敗
|
||||
mockOrderModel.EXPECT().DeleteByBusinessID(gomock.Any(), "B123").Return(nil, errors.New("delete failed")).Times(1)
|
||||
},
|
||||
expectErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// 設置測試環境
|
||||
tt.prepare()
|
||||
|
||||
// 初始化 DeleteOrderLogic
|
||||
logic := NewDeleteOrderLogic(context.TODO(), svcCtx)
|
||||
|
||||
// 執行 DeleteOrder
|
||||
resp, err := logic.DeleteOrder(tt.input)
|
||||
|
||||
// 驗證結果
|
||||
if tt.expectErr {
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, resp)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, resp)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ package orderservicelogic
|
|||
import (
|
||||
"app-cloudep-order-server/gen_result/pb/order"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
ers "code.30cm.net/digimon/library-go/errs"
|
||||
"github.com/shopspring/decimal"
|
||||
|
@ -45,6 +46,7 @@ func (l *GetOrderLogic) GetOrder(in *order.GetOrderReq) (*order.GetOrderResp, er
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Println(o)
|
||||
|
||||
return &order.GetOrderResp{
|
||||
UpdateTime: o.UpdateTime,
|
||||
|
@ -58,37 +60,55 @@ func (l *GetOrderLogic) GetOrder(in *order.GetOrderReq) (*order.GetOrderResp, er
|
|||
Count: o.Count.String(),
|
||||
OrderFee: o.OrderFee.String(),
|
||||
Amount: o.Amount.String(),
|
||||
// 下面的是未來擴充用,加密貨幣用,或者幣別轉換用,普通訂單用不到
|
||||
ReferenceBrand: o.ReferenceBrand,
|
||||
ReferenceUid: o.ReferenceUID,
|
||||
WalletStatus: o.WalletStatus,
|
||||
ThreePartyStatus: o.ThreePartyStatus,
|
||||
DirectionType: o.DirectionType,
|
||||
CryptoType: o.CryptoType,
|
||||
ThirdPartyFee: decimalToString(*o.ThirdPartyFee),
|
||||
CryptoToUsdtRate: decimalToString(*o.CryptoToUSDTRate),
|
||||
FiatToUsdRate: decimalToString(*o.FiatToUSDRate),
|
||||
FeeCryptoToUsdtRate: decimalToString(*o.FeeCryptoToUSDTRate),
|
||||
UsdtToCryptoTypeRate: decimalToString(*o.USDTToCryptoTypeRate),
|
||||
PaymentFiat: o.PaymentFiat,
|
||||
PaymentUnitPrice: decimalToString(*o.PaymentUnitPrice),
|
||||
PaymentTemplateId: o.PaymentTemplateID,
|
||||
OrderArrivalTime: o.OrderArrivalTime,
|
||||
OrderPaymentTime: o.OrderPaymentTime,
|
||||
UnpaidTimeoutSecond: o.UnpaidTimeoutSecond,
|
||||
ChainType: o.ChainType,
|
||||
TxHash: o.TxHash,
|
||||
FromAddress: o.FromAddress,
|
||||
ToAddress: o.ToAddress,
|
||||
ChainFee: decimalToString(*o.ChainFee),
|
||||
ChainFeeCrypto: o.ChainFeeCrypto,
|
||||
Memo: o.Memo,
|
||||
OrderNote: o.OrderNote,
|
||||
// 下面的為未來擴充用的欄位
|
||||
ReferenceBrand: nilString(o.ReferenceBrand),
|
||||
ReferenceUid: nilString(o.ReferenceUID),
|
||||
WalletStatus: nilInt64(o.WalletStatus),
|
||||
ThreePartyStatus: nilInt64(o.ThreePartyStatus),
|
||||
DirectionType: nilInt64(o.DirectionType),
|
||||
CryptoType: nilString(o.CryptoType),
|
||||
ThirdPartyFee: decimalToString(o.ThirdPartyFee),
|
||||
CryptoToUsdtRate: decimalToString(o.CryptoToUSDTRate),
|
||||
FiatToUsdRate: decimalToString(o.FiatToUSDRate),
|
||||
FeeCryptoToUsdtRate: decimalToString(o.FeeCryptoToUSDTRate),
|
||||
UsdtToCryptoTypeRate: decimalToString(o.USDTToCryptoTypeRate),
|
||||
PaymentFiat: nilString(o.PaymentFiat),
|
||||
PaymentUnitPrice: decimalToString(o.PaymentUnitPrice),
|
||||
PaymentTemplateId: nilString(o.PaymentTemplateID),
|
||||
OrderArrivalTime: nilInt64(o.OrderArrivalTime),
|
||||
OrderPaymentTime: nilInt64(o.OrderPaymentTime),
|
||||
UnpaidTimeoutSecond: nilInt64(o.UnpaidTimeoutSecond),
|
||||
ChainType: nilString(o.ChainType),
|
||||
TxHash: nilString(o.TxHash),
|
||||
FromAddress: nilString(o.FromAddress),
|
||||
ToAddress: nilString(o.ToAddress),
|
||||
ChainFee: decimalToString(o.ChainFee),
|
||||
ChainFeeCrypto: nilString(o.ChainFeeCrypto),
|
||||
Memo: nilString(o.Memo),
|
||||
OrderNote: nilString(o.OrderNote),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func decimalToString(amount decimal.Decimal) *string {
|
||||
func decimalToString(amount *decimal.Decimal) *string {
|
||||
if amount == nil {
|
||||
return nil
|
||||
}
|
||||
a := amount.String()
|
||||
|
||||
return &a
|
||||
}
|
||||
|
||||
func nilString(s *string) *string {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func nilInt64(i *int64) *int64 {
|
||||
if i == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return i
|
||||
}
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
package orderservicelogic
|
||||
|
||||
import (
|
||||
"app-cloudep-order-server/gen_result/pb/order"
|
||||
mocksvc "app-cloudep-order-server/internal/mock/lib"
|
||||
mockmodel "app-cloudep-order-server/internal/mock/model"
|
||||
model "app-cloudep-order-server/internal/model/mongo"
|
||||
"app-cloudep-order-server/internal/svc"
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/shopspring/decimal"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.uber.org/mock/gomock"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetOrder(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
// 初始化 mock 依賴
|
||||
mockOrderModel := mockmodel.NewMockOrderModel(ctrl)
|
||||
mockValidate := mocksvc.NewMockValidate(ctrl)
|
||||
|
||||
// 初始化服務上下文
|
||||
svcCtx := &svc.ServiceContext{
|
||||
OrderModel: mockOrderModel,
|
||||
Validate: mockValidate,
|
||||
}
|
||||
|
||||
// 模擬返回的訂單數據
|
||||
mockOrder := &model.Order{
|
||||
UpdateTime: 1630000000,
|
||||
CreateTime: 1620000000,
|
||||
BusinessID: "B123",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUID: "UID123",
|
||||
ReferenceID: "REF123",
|
||||
Count: decimal.RequireFromString("10.5"),
|
||||
OrderFee: decimal.RequireFromString("0.5"),
|
||||
Amount: decimal.RequireFromString("100"),
|
||||
}
|
||||
|
||||
// 測試數據集
|
||||
tests := []struct {
|
||||
name string
|
||||
input *order.GetOrderReq
|
||||
prepare func()
|
||||
expectErr bool
|
||||
expected *order.GetOrderResp
|
||||
}{
|
||||
{
|
||||
name: "成功取得訂單",
|
||||
input: &order.GetOrderReq{
|
||||
BusinessId: "B123",
|
||||
},
|
||||
prepare: func() {
|
||||
// 模擬驗證成功
|
||||
mockValidate.EXPECT().ValidateAll(gomock.Any()).Return(nil).Times(1)
|
||||
// 模擬查詢訂單成功
|
||||
mockOrderModel.EXPECT().FindOneBusinessID(gomock.Any(), "B123").Return(mockOrder, nil).Times(1)
|
||||
},
|
||||
expectErr: false,
|
||||
expected: &order.GetOrderResp{
|
||||
UpdateTime: 1630000000,
|
||||
CreateTime: 1620000000,
|
||||
BusinessId: "B123",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUid: "UID123",
|
||||
ReferenceId: "REF123",
|
||||
Count: "10.5",
|
||||
OrderFee: "0.5",
|
||||
Amount: "100",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "驗證失敗",
|
||||
input: &order.GetOrderReq{
|
||||
BusinessId: "B123",
|
||||
},
|
||||
prepare: func() {
|
||||
// 模擬驗證失敗
|
||||
mockValidate.EXPECT().ValidateAll(gomock.Any()).Return(errors.New("validation failed")).Times(1)
|
||||
},
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "查詢訂單失敗",
|
||||
input: &order.GetOrderReq{
|
||||
BusinessId: "B123",
|
||||
},
|
||||
prepare: func() {
|
||||
// 模擬驗證成功
|
||||
mockValidate.EXPECT().ValidateAll(gomock.Any()).Return(nil).Times(1)
|
||||
// 模擬查詢訂單失敗
|
||||
mockOrderModel.EXPECT().FindOneBusinessID(gomock.Any(), "B123").Return(nil, errors.New("order not found")).Times(1)
|
||||
},
|
||||
expectErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// 設置測試環境
|
||||
tt.prepare()
|
||||
|
||||
// 初始化 GetOrderLogic
|
||||
logic := NewGetOrderLogic(context.TODO(), svcCtx)
|
||||
|
||||
// 執行 GetOrder
|
||||
resp, err := logic.GetOrder(tt.input)
|
||||
|
||||
// 驗證結果
|
||||
if tt.expectErr {
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, resp)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.expected, resp)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -160,3 +160,8 @@ func ConvertOrdersToGetOrderResp(orders []model.Order) []*order.GetOrderResp {
|
|||
|
||||
return res
|
||||
}
|
||||
|
||||
// Helper functions
|
||||
func ptrString(s string) *string {
|
||||
return &s
|
||||
}
|
||||
|
|
|
@ -0,0 +1,458 @@
|
|||
package orderservicelogic
|
||||
|
||||
import (
|
||||
"app-cloudep-order-server/gen_result/pb/order"
|
||||
mocksvc "app-cloudep-order-server/internal/mock/lib"
|
||||
mockmodel "app-cloudep-order-server/internal/mock/model"
|
||||
model "app-cloudep-order-server/internal/model/mongo"
|
||||
"app-cloudep-order-server/internal/svc"
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/shopspring/decimal"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.uber.org/mock/gomock"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestConvertOrdersToGetOrderResp(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input []model.Order
|
||||
expected []*order.GetOrderResp
|
||||
}{
|
||||
{
|
||||
name: "空訂單列表",
|
||||
input: []model.Order{},
|
||||
expected: []*order.GetOrderResp{},
|
||||
},
|
||||
{
|
||||
name: "單筆訂單",
|
||||
input: []model.Order{
|
||||
{
|
||||
BusinessID: "B123",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUID: "UID123",
|
||||
ReferenceID: "REF123",
|
||||
Count: decimal.RequireFromString("10.5"),
|
||||
OrderFee: decimal.RequireFromString("0.5"),
|
||||
Amount: decimal.RequireFromString("100"),
|
||||
},
|
||||
},
|
||||
expected: []*order.GetOrderResp{
|
||||
{
|
||||
BusinessId: "B123",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUid: "UID123",
|
||||
ReferenceId: "REF123",
|
||||
Count: "10.5",
|
||||
OrderFee: "0.5",
|
||||
Amount: "100",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "多筆訂單",
|
||||
input: []model.Order{
|
||||
{
|
||||
BusinessID: "B123",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUID: "UID123",
|
||||
ReferenceID: "REF123",
|
||||
Count: decimal.RequireFromString("10.5"),
|
||||
OrderFee: decimal.RequireFromString("0.5"),
|
||||
Amount: decimal.RequireFromString("100"),
|
||||
},
|
||||
{
|
||||
BusinessID: "B456",
|
||||
OrderType: 2,
|
||||
OrderStatus: 3,
|
||||
Brand: "OtherBrand",
|
||||
OrderUID: "UID456",
|
||||
ReferenceID: "REF456",
|
||||
Count: decimal.RequireFromString("20"),
|
||||
OrderFee: decimal.RequireFromString("1"),
|
||||
Amount: decimal.RequireFromString("200"),
|
||||
},
|
||||
},
|
||||
expected: []*order.GetOrderResp{
|
||||
{
|
||||
BusinessId: "B123",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUid: "UID123",
|
||||
ReferenceId: "REF123",
|
||||
Count: "10.5",
|
||||
OrderFee: "0.5",
|
||||
Amount: "100",
|
||||
},
|
||||
{
|
||||
BusinessId: "B456",
|
||||
OrderType: 2,
|
||||
OrderStatus: 3,
|
||||
Brand: "OtherBrand",
|
||||
OrderUid: "UID456",
|
||||
ReferenceId: "REF456",
|
||||
Count: "20",
|
||||
OrderFee: "1",
|
||||
Amount: "200",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// 執行 ConvertOrdersToGetOrderResp 函數
|
||||
result := ConvertOrdersToGetOrderResp(tt.input)
|
||||
|
||||
// 驗證結果
|
||||
assert.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptionalString(t *testing.T) {
|
||||
t.Run("非 nil 字串", func(t *testing.T) {
|
||||
str := "hello"
|
||||
result := optionalString(&str)
|
||||
assert.NotNil(t, result)
|
||||
assert.Equal(t, &str, result)
|
||||
})
|
||||
|
||||
t.Run("nil 字串", func(t *testing.T) {
|
||||
result := optionalString(nil)
|
||||
assert.Nil(t, result)
|
||||
})
|
||||
}
|
||||
|
||||
func TestOptionalInt64(t *testing.T) {
|
||||
t.Run("非 nil int64", func(t *testing.T) {
|
||||
num := int64(123)
|
||||
result := optionalInt64(&num)
|
||||
assert.NotNil(t, result)
|
||||
assert.Equal(t, &num, result)
|
||||
})
|
||||
|
||||
t.Run("nil int64", func(t *testing.T) {
|
||||
result := optionalInt64(nil)
|
||||
assert.Nil(t, result)
|
||||
})
|
||||
}
|
||||
|
||||
func TestOptionalDecimalToString(t *testing.T) {
|
||||
t.Run("非 nil decimal", func(t *testing.T) {
|
||||
dec := decimal.NewFromInt(123)
|
||||
expected := "123"
|
||||
result := optionalDecimalToString(&dec)
|
||||
assert.NotNil(t, result)
|
||||
assert.Equal(t, &expected, result)
|
||||
})
|
||||
|
||||
t.Run("nil decimal", func(t *testing.T) {
|
||||
result := optionalDecimalToString(nil)
|
||||
assert.Nil(t, result)
|
||||
})
|
||||
}
|
||||
|
||||
func TestConvertOrderToGetOrderResp(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input model.Order
|
||||
expected *order.GetOrderResp
|
||||
}{
|
||||
{
|
||||
name: "所有欄位都有值",
|
||||
input: model.Order{
|
||||
BusinessID: "B123",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUID: "UID123",
|
||||
ReferenceID: "REF123",
|
||||
Count: decimal.RequireFromString("10.5"),
|
||||
OrderFee: decimal.RequireFromString("0.5"),
|
||||
Amount: decimal.RequireFromString("100"),
|
||||
ReferenceBrand: ptrString("OtherBrand"),
|
||||
ReferenceUID: ptrString("REFUID"),
|
||||
WalletStatus: ptrInt64(1),
|
||||
ThreePartyStatus: ptrInt64(2),
|
||||
DirectionType: ptrInt64(1),
|
||||
CryptoType: ptrString("BTC"),
|
||||
ThirdPartyFee: decimalPtrFromString("0.01"),
|
||||
CryptoToUSDTRate: decimalPtrFromString("50000"),
|
||||
FiatToUSDRate: decimalPtrFromString("1"),
|
||||
FeeCryptoToUSDTRate: decimalPtrFromString("0.02"),
|
||||
USDTToCryptoTypeRate: decimalPtrFromString("0.00002"),
|
||||
PaymentFiat: ptrString("USD"),
|
||||
PaymentUnitPrice: decimalPtrFromString("50000"),
|
||||
PaymentTemplateID: ptrString("TEMPLATE123"),
|
||||
OrderArrivalTime: ptrInt64(1630000000),
|
||||
OrderPaymentTime: ptrInt64(1620000000),
|
||||
UnpaidTimeoutSecond: ptrInt64(3600),
|
||||
ChainType: ptrString("ETH"),
|
||||
TxHash: ptrString("0xABC123"),
|
||||
FromAddress: ptrString("0xFROM123"),
|
||||
ToAddress: ptrString("0xTO123"),
|
||||
ChainFee: decimalPtrFromString("0.001"),
|
||||
ChainFeeCrypto: ptrString("ETH"),
|
||||
Memo: ptrString("Test Memo"),
|
||||
OrderNote: ptrString("Test Note"),
|
||||
CreateTime: 1620000000,
|
||||
UpdateTime: 1630000000,
|
||||
},
|
||||
expected: &order.GetOrderResp{
|
||||
BusinessId: "B123",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUid: "UID123",
|
||||
ReferenceId: "REF123",
|
||||
Count: "10.5",
|
||||
OrderFee: "0.5",
|
||||
Amount: "100",
|
||||
ReferenceBrand: ptrString("OtherBrand"),
|
||||
ReferenceUid: ptrString("REFUID"),
|
||||
WalletStatus: ptrInt64(1),
|
||||
ThreePartyStatus: ptrInt64(2),
|
||||
DirectionType: ptrInt64(1),
|
||||
CryptoType: ptrString("BTC"),
|
||||
ThirdPartyFee: ptrString("0.01"),
|
||||
CryptoToUsdtRate: ptrString("50000"),
|
||||
FiatToUsdRate: ptrString("1"),
|
||||
FeeCryptoToUsdtRate: ptrString("0.02"),
|
||||
UsdtToCryptoTypeRate: ptrString("0.00002"),
|
||||
PaymentFiat: ptrString("USD"),
|
||||
PaymentUnitPrice: ptrString("50000"),
|
||||
PaymentTemplateId: ptrString("TEMPLATE123"),
|
||||
OrderArrivalTime: ptrInt64(1630000000),
|
||||
OrderPaymentTime: ptrInt64(1620000000),
|
||||
UnpaidTimeoutSecond: ptrInt64(3600),
|
||||
ChainType: ptrString("ETH"),
|
||||
TxHash: ptrString("0xABC123"),
|
||||
FromAddress: ptrString("0xFROM123"),
|
||||
ToAddress: ptrString("0xTO123"),
|
||||
ChainFee: ptrString("0.001"),
|
||||
ChainFeeCrypto: ptrString("ETH"),
|
||||
Memo: ptrString("Test Memo"),
|
||||
OrderNote: ptrString("Test Note"),
|
||||
CreateTime: 1620000000,
|
||||
UpdateTime: 1630000000,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "部分欄位為 nil",
|
||||
input: model.Order{
|
||||
BusinessID: "B456",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUID: "UID456",
|
||||
ReferenceID: "REF456",
|
||||
Count: decimal.RequireFromString("10"),
|
||||
OrderFee: decimal.RequireFromString("1"),
|
||||
Amount: decimal.RequireFromString("100"),
|
||||
ReferenceBrand: nil,
|
||||
ReferenceUID: nil,
|
||||
WalletStatus: nil,
|
||||
ThreePartyStatus: nil,
|
||||
DirectionType: nil,
|
||||
CryptoType: nil,
|
||||
ThirdPartyFee: nil,
|
||||
CryptoToUSDTRate: nil,
|
||||
FiatToUSDRate: nil,
|
||||
FeeCryptoToUSDTRate: nil,
|
||||
USDTToCryptoTypeRate: nil,
|
||||
PaymentFiat: nil,
|
||||
PaymentUnitPrice: nil,
|
||||
PaymentTemplateID: nil,
|
||||
OrderArrivalTime: nil,
|
||||
OrderPaymentTime: nil,
|
||||
UnpaidTimeoutSecond: nil,
|
||||
ChainType: nil,
|
||||
TxHash: nil,
|
||||
FromAddress: nil,
|
||||
ToAddress: nil,
|
||||
ChainFee: nil,
|
||||
ChainFeeCrypto: nil,
|
||||
Memo: nil,
|
||||
OrderNote: nil,
|
||||
CreateTime: 1620000000,
|
||||
UpdateTime: 1630000000,
|
||||
},
|
||||
expected: &order.GetOrderResp{
|
||||
BusinessId: "B456",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUid: "UID456",
|
||||
ReferenceId: "REF456",
|
||||
Count: "10",
|
||||
OrderFee: "1",
|
||||
Amount: "100",
|
||||
ReferenceBrand: nil,
|
||||
ReferenceUid: nil,
|
||||
WalletStatus: nil,
|
||||
ThreePartyStatus: nil,
|
||||
DirectionType: nil,
|
||||
CryptoType: nil,
|
||||
ThirdPartyFee: nil,
|
||||
CryptoToUsdtRate: nil,
|
||||
FiatToUsdRate: nil,
|
||||
FeeCryptoToUsdtRate: nil,
|
||||
UsdtToCryptoTypeRate: nil,
|
||||
PaymentFiat: nil,
|
||||
PaymentUnitPrice: nil,
|
||||
PaymentTemplateId: nil,
|
||||
OrderArrivalTime: nil,
|
||||
OrderPaymentTime: nil,
|
||||
UnpaidTimeoutSecond: nil,
|
||||
ChainType: nil,
|
||||
TxHash: nil,
|
||||
FromAddress: nil,
|
||||
ToAddress: nil,
|
||||
ChainFee: nil,
|
||||
ChainFeeCrypto: nil,
|
||||
Memo: nil,
|
||||
OrderNote: nil,
|
||||
CreateTime: 1620000000,
|
||||
UpdateTime: 1630000000,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// 執行 ConvertOrderToGetOrderResp 函數
|
||||
result := ConvertOrderToGetOrderResp(tt.input)
|
||||
|
||||
// 驗證結果
|
||||
assert.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestListOrder(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
// 初始化 mock 依賴
|
||||
mockOrderModel := mockmodel.NewMockOrderModel(ctrl)
|
||||
mockValidate := mocksvc.NewMockValidate(ctrl)
|
||||
|
||||
// 初始化服務上下文
|
||||
svcCtx := &svc.ServiceContext{
|
||||
OrderModel: mockOrderModel,
|
||||
Validate: mockValidate,
|
||||
}
|
||||
|
||||
// 測試數據集
|
||||
tests := []struct {
|
||||
name string
|
||||
input *order.ListOrderReq
|
||||
prepare func()
|
||||
expectErr bool
|
||||
expectedRes *order.ListOrderResp
|
||||
}{
|
||||
{
|
||||
name: "成功取得訂單列表",
|
||||
input: &order.ListOrderReq{
|
||||
PageIndex: 1,
|
||||
PageSize: 10,
|
||||
},
|
||||
prepare: func() {
|
||||
// 模擬驗證成功
|
||||
mockValidate.EXPECT().ValidateAll(gomock.Any()).Return(nil).Times(1)
|
||||
// 模擬返回訂單列表
|
||||
mockOrderModel.EXPECT().ListOrder(gomock.Any(), gomock.Any()).Return([]model.Order{
|
||||
{
|
||||
BusinessID: "B123",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUID: "UID123",
|
||||
ReferenceID: "REF123",
|
||||
Count: decimal.RequireFromString("10.5"),
|
||||
OrderFee: decimal.RequireFromString("0.5"),
|
||||
Amount: decimal.RequireFromString("100"),
|
||||
},
|
||||
}, int64(1), nil).Times(1)
|
||||
},
|
||||
expectErr: false,
|
||||
expectedRes: &order.ListOrderResp{
|
||||
Data: []*order.GetOrderResp{
|
||||
{
|
||||
BusinessId: "B123",
|
||||
OrderType: 1,
|
||||
OrderStatus: 2,
|
||||
Brand: "TestBrand",
|
||||
OrderUid: "UID123",
|
||||
ReferenceId: "REF123",
|
||||
Count: "10.5",
|
||||
OrderFee: "0.5",
|
||||
Amount: "100",
|
||||
},
|
||||
},
|
||||
Page: &order.Pager{
|
||||
Total: 1,
|
||||
Index: 1,
|
||||
Size: 10,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "訂單查詢失敗",
|
||||
input: &order.ListOrderReq{
|
||||
PageIndex: 1,
|
||||
PageSize: 10,
|
||||
},
|
||||
prepare: func() {
|
||||
// 模擬驗證成功
|
||||
mockValidate.EXPECT().ValidateAll(gomock.Any()).Return(nil).Times(1)
|
||||
// 模擬返回查詢錯誤
|
||||
mockOrderModel.EXPECT().ListOrder(gomock.Any(), gomock.Any()).Return(nil, int64(0), errors.New("query failed")).Times(1)
|
||||
},
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "分頁錯誤",
|
||||
input: &order.ListOrderReq{
|
||||
PageIndex: 0,
|
||||
PageSize: 10,
|
||||
},
|
||||
prepare: func() {
|
||||
// 模擬驗證失敗,因為 PageIndex 為 0
|
||||
mockValidate.EXPECT().ValidateAll(gomock.Any()).Return(errors.New("invalid pagination")).Times(1)
|
||||
},
|
||||
expectErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// 準備測試環境
|
||||
tt.prepare()
|
||||
|
||||
// 初始化 ListOrderLogic
|
||||
logic := NewListOrderLogic(context.TODO(), svcCtx)
|
||||
|
||||
// 執行 ListOrder
|
||||
resp, err := logic.ListOrder(tt.input)
|
||||
|
||||
// 驗證結果
|
||||
if tt.expectErr {
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, resp)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.expectedRes, resp)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
package orderservicelogic
|
||||
|
||||
import (
|
||||
"app-cloudep-order-server/gen_result/pb/order"
|
||||
"context"
|
||||
|
||||
"app-cloudep-order-server/internal/svc"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type ModifyOrderLogic struct {
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
logx.Logger
|
||||
}
|
||||
|
||||
func NewModifyOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ModifyOrderLogic {
|
||||
return &ModifyOrderLogic{
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
Logger: logx.WithContext(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
// ModifyOrder 修改訂單
|
||||
func (l *ModifyOrderLogic) ModifyOrder(in *order.ModifyOrderReq) (*order.OKResp, error) {
|
||||
// todo: add your logic here and delete this line
|
||||
|
||||
return &order.OKResp{}, nil
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: ./validate.go
|
||||
//
|
||||
// Generated by this command:
|
||||
//
|
||||
// mockgen -source=./validate.go -destination=../../mock/lib/validate.go -package=lib
|
||||
//
|
||||
|
||||
// Package lib is a generated GoMock package.
|
||||
package lib
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
|
||||
required "code.30cm.net/digimon/library-go/validator"
|
||||
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
// MockValidate is a mock of Validate interface.
|
||||
type MockValidate struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockValidateMockRecorder
|
||||
}
|
||||
|
||||
// MockValidateMockRecorder is the mock recorder for MockValidate.
|
||||
type MockValidateMockRecorder struct {
|
||||
mock *MockValidate
|
||||
}
|
||||
|
||||
// NewMockValidate creates a new mock instance.
|
||||
func NewMockValidate(ctrl *gomock.Controller) *MockValidate {
|
||||
mock := &MockValidate{ctrl: ctrl}
|
||||
mock.recorder = &MockValidateMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockValidate) EXPECT() *MockValidateMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// BindToValidator mocks base method.
|
||||
func (m *MockValidate) BindToValidator(opts ...required.Option) error {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []any{}
|
||||
for _, a := range opts {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "BindToValidator", varargs...)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// BindToValidator indicates an expected call of BindToValidator.
|
||||
func (mr *MockValidateMockRecorder) BindToValidator(opts ...any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BindToValidator", reflect.TypeOf((*MockValidate)(nil).BindToValidator), opts...)
|
||||
}
|
||||
|
||||
// ValidateAll mocks base method.
|
||||
func (m *MockValidate) ValidateAll(obj any) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ValidateAll", obj)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ValidateAll indicates an expected call of ValidateAll.
|
||||
func (mr *MockValidateMockRecorder) ValidateAll(obj any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateAll", reflect.TypeOf((*MockValidate)(nil).ValidateAll), obj)
|
||||
}
|
|
@ -143,8 +143,10 @@ func (m *customOrderModel) DeleteByBusinessID(ctx context.Context, id string) (*
|
|||
|
||||
func (m *defaultOrderModel) FindOneBusinessID(ctx context.Context, id string) (*Order, error) {
|
||||
var data Order
|
||||
filter := bson.M{"delete_time": bson.M{"$in": []any{0, nil}}}
|
||||
filter["business_id"] = id
|
||||
|
||||
err := m.conn.FindOne(ctx, &data, bson.M{"business_id": id})
|
||||
err := m.conn.FindOne(ctx, &data, filter)
|
||||
switch {
|
||||
case err == nil:
|
||||
return &data, nil
|
||||
|
|
|
@ -34,11 +34,6 @@ func (s *OrderServiceServer) CancelOrder(ctx context.Context, in *order.CancelOr
|
|||
return l.CancelOrder(in)
|
||||
}
|
||||
|
||||
// ModifyOrder 修改訂單
|
||||
func (s *OrderServiceServer) ModifyOrder(ctx context.Context, in *order.ModifyOrderReq) (*order.OKResp, error) {
|
||||
l := orderservicelogic.NewModifyOrderLogic(ctx, s.svcCtx)
|
||||
return l.ModifyOrder(in)
|
||||
}
|
||||
|
||||
// ModifyOrderStatus 修改訂單狀態
|
||||
func (s *OrderServiceServer) ModifyOrderStatus(ctx context.Context, in *order.ModifyOrderStatusReq) (*order.OKResp, error) {
|
||||
|
|
Loading…
Reference in New Issue