package usecase import ( "app-cloudep-trade-service/internal/domain/order" "app-cloudep-trade-service/internal/domain/usecase" mockmodel "app-cloudep-trade-service/internal/mock/model" model "app-cloudep-trade-service/internal/model/mongo" "context" "errors" "time" "github.com/go-playground/assert/v2" "github.com/shopspring/decimal" "github.com/zeromicro/go-zero/core/stores/mon" "go.uber.org/mock/gomock" "testing" ) func TestOrderUseCase_CancelOrder(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() // 初始化 mock 依賴 mockOrderModel := mockmodel.NewMockOrderModel(ctrl) orderUseCase := &OrderUseCase{ OrderModel: mockOrderModel, } cancelOrderQuery := usecase.CancelOrderQuery{ BusinessID: "business_123", Status: order.Cancelled, // 使用模擬的狀態 } tests := []struct { name string mockSetup func() param usecase.CancelOrderQuery wantErr bool }{ { name: "successful order cancellation", mockSetup: func() { mockOrderModel.EXPECT().UpdateStatus(gomock.Any(), model.UpdateStatusReq{ BusinessID: cancelOrderQuery.BusinessID, Status: cancelOrderQuery.Status.ToInt64(), }).Return(nil, nil) }, param: cancelOrderQuery, wantErr: false, }, { name: "failed order cancellation", mockSetup: func() { mockOrderModel.EXPECT().UpdateStatus(gomock.Any(), model.UpdateStatusReq{ BusinessID: cancelOrderQuery.BusinessID, Status: cancelOrderQuery.Status.ToInt64(), }).Return(nil, errors.New("update error")) }, param: cancelOrderQuery, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.mockSetup() // 設置每個測試用例的 mock 行為 err := orderUseCase.CancelOrder(context.Background(), tt.param) if (err != nil) != tt.wantErr { t.Errorf("CancelOrder() error = %v, wantErr %v", err, tt.wantErr) } }) } } func TestOrderUseCase_CreateOrder(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() // 初始化 mock 依賴 mockOrderModel := mockmodel.NewMockOrderModel(mockCtrl) orderUseCase := &OrderUseCase{ OrderModel: mockOrderModel, } now := time.Now().UTC().UnixNano() // 構建測試參數 createOrderReq := usecase.CreateOrderReq{ BusinessID: "business_123", OrderType: order.TestType, OrderStatus: order.Created, Brand: "test_brand", OrderUID: "user_123", ReferenceID: "reference_123", Count: decimal.NewFromInt(2), OrderFee: decimal.NewFromFloat(0.01), Amount: decimal.NewFromFloat(100.0), ReferenceBrand: StringPtr("reference_brand"), ReferenceUID: StringPtr("reference_uid"), WalletStatus: 1, ThreePartyStatus: Int64Ptr(2), DirectionType: 1, CryptoType: StringPtr("BTC"), PaymentFiat: StringPtr("USD"), PaymentTemplateID: StringPtr("template_001"), OrderArrivalTime: Int64Ptr(now), OrderPaymentTime: Int64Ptr(now), UnpaidTimeoutSecond: Int64Ptr(3600), ChainType: StringPtr("mainnet"), TxHash: StringPtr("tx_hash_123"), FromAddress: StringPtr("from_address"), ToAddress: StringPtr("to_address"), ChainFeeCrypto: StringPtr("ETH"), Memo: StringPtr("test memo"), OrderNote: StringPtr("test order note"), } tests := []struct { name string mockSetup func() param usecase.CreateOrderReq wantErr bool }{ { name: "successful order creation", mockSetup: func() { mockOrderModel.EXPECT().Insert(gomock.Any(), gomock.Any()).Return(nil) }, param: createOrderReq, wantErr: false, }, { name: "failed order creation", mockSetup: func() { mockOrderModel.EXPECT().Insert(gomock.Any(), gomock.Any()).Return(errors.New("insert error")) }, param: createOrderReq, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.mockSetup() // 設置每個測試用例的 mock 行為 err := orderUseCase.CreateOrder(context.Background(), tt.param) if (err != nil) != tt.wantErr { t.Errorf("CreateOrder() error = %v, wantErr %v", err, tt.wantErr) } }) } } func TestOrderUseCase_DeleteOrder(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() // 初始化 mock 依賴 mockOrderModel := mockmodel.NewMockOrderModel(ctrl) orderUseCase := &OrderUseCase{ OrderModel: mockOrderModel, } // 構建測試參數 deleteOrderQuery := usecase.DeleteOrderQuery{ BusinessID: "business_123", } tests := []struct { name string mockSetup func() param usecase.DeleteOrderQuery wantErr bool }{ { name: "successful order deletion", mockSetup: func() { mockOrderModel.EXPECT().DeleteByBusinessID(gomock.Any(), deleteOrderQuery.BusinessID).Return(nil, nil) }, param: deleteOrderQuery, wantErr: false, }, { name: "failed order deletion", mockSetup: func() { mockOrderModel.EXPECT().DeleteByBusinessID(gomock.Any(), deleteOrderQuery.BusinessID).Return(nil, errors.New("delete error")) }, param: deleteOrderQuery, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.mockSetup() // 設置每個測試用例的 mock 行為 err := orderUseCase.DeleteOrder(context.Background(), tt.param) if (err != nil) != tt.wantErr { t.Errorf("DeleteOrder() error = %v, wantErr %v", err, tt.wantErr) } }) } } func TestOrderUseCase_GetOrder(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() // 初始化 mock 依賴 mockOrderModel := mockmodel.NewMockOrderModel(mockCtrl) orderUseCase := &OrderUseCase{ OrderModel: mockOrderModel, } getOrderQuery := usecase.GetOrderQuery{ BusinessID: "business_123", } // 構建測試用例返回的 Order mockOrder := &model.Order{ UpdateTime: 123456789, CreateTime: 123456789, BusinessID: "business_123", OrderType: order.TestType, OrderStatus: order.Created, Brand: "test_brand", OrderUID: "user_123", ReferenceID: "reference_123", Count: decimal.NewFromInt(2), OrderFee: decimal.NewFromFloat(0.01), Amount: decimal.NewFromFloat(100.0), ReferenceBrand: StringPtr("reference_brand"), ReferenceUID: StringPtr("reference_uid"), WalletStatus: 1, ThreePartyStatus: Int64Ptr(2), DirectionType: 1, CryptoType: StringPtr("BTC"), PaymentFiat: StringPtr("USD"), PaymentTemplateID: StringPtr("template_001"), OrderArrivalTime: Int64Ptr(123456789), OrderPaymentTime: Int64Ptr(123456789), UnpaidTimeoutSecond: Int64Ptr(3600), ChainType: StringPtr("mainnet"), TxHash: StringPtr("tx_hash_123"), FromAddress: StringPtr("from_address"), ToAddress: StringPtr("to_address"), ChainFeeCrypto: StringPtr("ETH"), Memo: StringPtr("test memo"), OrderNote: StringPtr("test order note"), } tests := []struct { name string mockSetup func() param usecase.GetOrderQuery wantResp *usecase.GetOrderResp wantErr bool }{ { name: "successful order retrieval", mockSetup: func() { mockOrderModel.EXPECT().FindOneBusinessID(gomock.Any(), getOrderQuery.BusinessID).Return(mockOrder, nil) }, param: getOrderQuery, wantResp: &usecase.GetOrderResp{ // 构建预期响应 UpdateTime: mockOrder.UpdateTime, CreateTime: mockOrder.CreateTime, BusinessID: mockOrder.BusinessID, OrderType: mockOrder.OrderType, OrderStatus: mockOrder.OrderStatus, Brand: mockOrder.Brand, OrderUID: mockOrder.OrderUID, ReferenceID: mockOrder.ReferenceID, Count: mockOrder.Count.String(), OrderFee: mockOrder.OrderFee.String(), Amount: mockOrder.Amount.String(), ReferenceBrand: mockOrder.ReferenceBrand, ReferenceUID: mockOrder.ReferenceUID, WalletStatus: Int64Ptr(mockOrder.WalletStatus), ThreePartyStatus: mockOrder.ThreePartyStatus, DirectionType: Int64Ptr(mockOrder.DirectionType), CryptoType: mockOrder.CryptoType, PaymentFiat: mockOrder.PaymentFiat, PaymentTemplateID: mockOrder.PaymentTemplateID, OrderArrivalTime: mockOrder.OrderArrivalTime, OrderPaymentTime: mockOrder.OrderPaymentTime, UnpaidTimeoutSecond: mockOrder.UnpaidTimeoutSecond, ChainType: mockOrder.ChainType, TxHash: mockOrder.TxHash, FromAddress: mockOrder.FromAddress, ToAddress: mockOrder.ToAddress, ChainFeeCrypto: mockOrder.ChainFeeCrypto, Memo: mockOrder.Memo, OrderNote: mockOrder.OrderNote, }, wantErr: false, }, { name: "order not found", mockSetup: func() { mockOrderModel.EXPECT().FindOneBusinessID(gomock.Any(), getOrderQuery.BusinessID).Return(nil, mon.ErrNotFound) }, param: getOrderQuery, wantResp: nil, wantErr: true, }, { name: "database error", mockSetup: func() { mockOrderModel.EXPECT().FindOneBusinessID(gomock.Any(), getOrderQuery.BusinessID).Return(nil, errors.New("database error")) }, param: getOrderQuery, wantResp: nil, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.mockSetup() // 設置每個測試用例的 mock 行為 resp, err := orderUseCase.GetOrder(context.Background(), tt.param) if (err != nil) != tt.wantErr { t.Errorf("GetOrder() error = %v, wantErr %v", err, tt.wantErr) return } assert.Equal(t, tt.wantResp, resp) }) } } func TestOrderUseCase_ListOrder(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() mockOrderModel := mockmodel.NewMockOrderModel(mockCtrl) orderUseCase := &OrderUseCase{ OrderModel: mockOrderModel, } listOrderQuery := usecase.GetOrderListReq{ PageIndex: 1, PageSize: 10, BusinessID: "business_123", OrderStatus: []int64{int64(order.Created)}, } mockOrders := []model.Order{ { BusinessID: "business_123", OrderUID: "user_123", OrderStatus: order.Created, // 其他欄位根據需要填充 }, } mockTotal := int64(1) tests := []struct { name string mockSetup func() param usecase.GetOrderListReq wantResp *usecase.ListOrderResp wantErr bool }{ { name: "successful order listing", mockSetup: func() { mockOrderModel.EXPECT().ListOrder(gomock.Any(), gomock.Any()).Return(mockOrders, mockTotal, nil) }, param: listOrderQuery, wantResp: &usecase.ListOrderResp{ Data: orderUseCase.convertOrdersToResponses(mockOrders), Page: &usecase.Pager{ Total: mockTotal, Index: listOrderQuery.PageIndex, Size: listOrderQuery.PageSize, }, }, wantErr: false, }, { name: "order listing error", mockSetup: func() { mockOrderModel.EXPECT().ListOrder(gomock.Any(), gomock.Any()).Return(nil, int64(0), errors.New("listing error")) }, param: listOrderQuery, wantResp: nil, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.mockSetup() resp, err := orderUseCase.ListOrder(context.Background(), tt.param) if (err != nil) != tt.wantErr { t.Errorf("ListOrder() error = %v, wantErr %v", err, tt.wantErr) return } assert.Equal(t, tt.wantResp, resp) }) } } func TestOrderUseCase_ModifyOrderStatus(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() mockOrderModel := mockmodel.NewMockOrderModel(mockCtrl) orderUseCase := &OrderUseCase{ OrderModel: mockOrderModel, } modifyOrderQuery := &usecase.ModifyOrderQuery{ BusinessID: "business_123", Status: int64(order.Cancelled), } tests := []struct { name string mockSetup func() param *usecase.ModifyOrderQuery wantErr bool }{ { name: "successful order status modification", mockSetup: func() { mockOrderModel.EXPECT().UpdateStatus(gomock.Any(), model.UpdateStatusReq{ BusinessID: modifyOrderQuery.BusinessID, Status: modifyOrderQuery.Status, }).Return(nil, nil) }, param: modifyOrderQuery, wantErr: false, }, { name: "order status modification error", mockSetup: func() { mockOrderModel.EXPECT().UpdateStatus(gomock.Any(), model.UpdateStatusReq{ BusinessID: modifyOrderQuery.BusinessID, Status: modifyOrderQuery.Status, }).Return(nil, errors.New("update error")) }, param: modifyOrderQuery, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.mockSetup() err := orderUseCase.ModifyOrderStatus(context.Background(), tt.param) if (err != nil) != tt.wantErr { t.Errorf("ModifyOrderStatus() error = %v, wantErr %v", err, tt.wantErr) } }) } } func TestOrderUseCase_OrderStatusTimeout(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() mockOrderModel := mockmodel.NewMockOrderModel(mockCtrl) orderUseCase := &OrderUseCase{ OrderModel: mockOrderModel, } tests := []struct { name string mockSetup func() wantErr bool }{ { name: "successful timeout update", mockSetup: func() { mockOrderModel.EXPECT().UpdateTimeoutOrder(gomock.Any(), gomock.Any()).Return(nil, nil) }, wantErr: false, }, { name: "timeout update error", mockSetup: func() { mockOrderModel.EXPECT().UpdateTimeoutOrder(gomock.Any(), gomock.Any()).Return(nil, errors.New("timeout error")) }, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.mockSetup() err := orderUseCase.OrderStatusTimeout(context.Background()) if (err != nil) != tt.wantErr { t.Errorf("OrderStatusTimeout() error = %v, wantErr %v", err, tt.wantErr) } }) } }