Files
zsp-project/backend/test/delivery_handler_test.go
2026-06-03 20:59:39 +08:00

376 lines
14 KiB
Go
Executable File

package test
import (
"bytes"
"encoding/json"
"errors"
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/rovina/zsp-backend/internal/handler"
"github.com/rovina/zsp-backend/internal/model"
"github.com/rovina/zsp-backend/internal/service"
"gorm.io/gorm"
)
// mockDeliveryService implements service.DeliveryService for testing
type mockDeliveryService struct {
listApplyFn func(page, pageSize int, orderNumber, blNumber, status string) ([]model.DeliveryApply, int64, error)
getApplyByIDFn func(id uint) (*model.DeliveryApply, error)
createApplyFn func(e *model.DeliveryApply) error
deleteApplyFn func(id uint) error
listOutboundFn func(page, pageSize int, outboundNumber, blNumber, status string) ([]model.DeliveryOutbound, int64, error)
getOutboundByIDFn func(id uint) (*model.DeliveryOutbound, error)
createOutboundFn func(e *model.DeliveryOutbound) error
deleteOutboundFn func(id uint) error
listWarehousesFn func() ([]model.Warehouse, error)
createWarehouseFn func(e *model.Warehouse) error
deleteWarehouseFn func(id uint) error
listInboundFn func(page, pageSize int, warehouse, commodity string) ([]model.InventoryInbound, int64, error)
createInboundFn func(e *model.InventoryInbound) error
deleteInboundFn func(id uint) error
listOwnershipFn func(page, pageSize int, transferNumber, blNumber, status string) ([]model.OwnershipTransfer, int64, error)
deleteOwnershipFn func(id uint) error
dbFn func() *gorm.DB
}
func (m *mockDeliveryService) ListApply(page, pageSize int, orderNumber, blNumber, status string) ([]model.DeliveryApply, int64, error) {
return m.listApplyFn(page, pageSize, orderNumber, blNumber, status)
}
func (m *mockDeliveryService) GetApplyByID(id uint) (*model.DeliveryApply, error) { return m.getApplyByIDFn(id) }
func (m *mockDeliveryService) CreateApply(e *model.DeliveryApply) error { return m.createApplyFn(e) }
func (m *mockDeliveryService) UpdateApply(e *model.DeliveryApply) error { return nil }
func (m *mockDeliveryService) DeleteApply(id uint) error { return m.deleteApplyFn(id) }
func (m *mockDeliveryService) ListOutbound(page, pageSize int, outboundNumber, blNumber, status string) ([]model.DeliveryOutbound, int64, error) {
return m.listOutboundFn(page, pageSize, outboundNumber, blNumber, status)
}
func (m *mockDeliveryService) GetOutboundByID(id uint) (*model.DeliveryOutbound, error) { return m.getOutboundByIDFn(id) }
func (m *mockDeliveryService) CreateOutbound(e *model.DeliveryOutbound) error { return m.createOutboundFn(e) }
func (m *mockDeliveryService) UpdateOutbound(e *model.DeliveryOutbound) error { return nil }
func (m *mockDeliveryService) DeleteOutbound(id uint) error { return m.deleteOutboundFn(id) }
func (m *mockDeliveryService) ListWarehouses() ([]model.Warehouse, error) { return m.listWarehousesFn() }
func (m *mockDeliveryService) GetWarehouseByID(id uint) (*model.Warehouse, error) { return nil, nil }
func (m *mockDeliveryService) CreateWarehouse(e *model.Warehouse) error { return m.createWarehouseFn(e) }
func (m *mockDeliveryService) UpdateWarehouse(e *model.Warehouse) error { return nil }
func (m *mockDeliveryService) DeleteWarehouse(id uint) error { return m.deleteWarehouseFn(id) }
func (m *mockDeliveryService) ListInbound(page, pageSize int, warehouse, commodity string) ([]model.InventoryInbound, int64, error) {
return m.listInboundFn(page, pageSize, warehouse, commodity)
}
func (m *mockDeliveryService) GetInboundByID(id uint) (*model.InventoryInbound, error) { return nil, nil }
func (m *mockDeliveryService) CreateInbound(e *model.InventoryInbound) error { return m.createInboundFn(e) }
func (m *mockDeliveryService) UpdateInbound(e *model.InventoryInbound) error { return nil }
func (m *mockDeliveryService) DeleteInbound(id uint) error { return m.deleteInboundFn(id) }
func (m *mockDeliveryService) ListOwnership(page, pageSize int, transferNumber, blNumber, status string) ([]model.OwnershipTransfer, int64, error) {
return m.listOwnershipFn(page, pageSize, transferNumber, blNumber, status)
}
func (m *mockDeliveryService) GetOwnershipByID(id uint) (*model.OwnershipTransfer, error) { return nil, nil }
func (m *mockDeliveryService) CreateOwnership(e *model.OwnershipTransfer) error { return nil }
func (m *mockDeliveryService) DeleteOwnership(id uint) error { return m.deleteOwnershipFn(id) }
func (m *mockDeliveryService) CreateOwnershipFiles(files []model.OwnershipTransferFile) error { return nil }
func (m *mockDeliveryService) DB() *gorm.DB { return nil }
var _ service.DeliveryService = (*mockDeliveryService)(nil)
func setupDeliveryRouter(h *handler.DeliveryHandler) *gin.Engine {
gin.SetMode(gin.TestMode)
r := gin.New()
api := r.Group("/api")
{
applyDelivery := api.Group("/apply-delivery")
{
applyDelivery.GET("", h.ListApply)
applyDelivery.POST("", h.CreateApply)
applyDelivery.DELETE("/:id", h.DeleteApply)
}
deliveryDetails := api.Group("/delivery-details")
{
deliveryDetails.GET("", h.ListOutbound)
deliveryDetails.POST("", h.CreateOutbound)
deliveryDetails.DELETE("/:id", h.DeleteOutbound)
}
inventory := api.Group("/inventory")
{
inventory.GET("/warehouses", h.ListWarehouses)
inventory.POST("/warehouses", h.CreateWarehouse)
inventory.DELETE("/warehouses/:id", h.DeleteWarehouse)
inventory.POST("/inbound", h.CreateInbound)
inventory.DELETE("/inbound/:id", h.DeleteInbound)
}
ownershipTransfer := api.Group("/ownership-transfer")
{
ownershipTransfer.GET("", h.ListOwnership)
ownershipTransfer.DELETE("/:id", h.DeleteOwnership)
}
}
return r
}
// ========== 我要提货 /api/apply-delivery ==========
func TestDeliveryListApply_Success(t *testing.T) {
mock := &mockDeliveryService{
listApplyFn: func(page, pageSize int, orderNumber, blNumber, status string) ([]model.DeliveryApply, int64, error) {
return []model.DeliveryApply{
{ID: 1, OrderNumber: "DA001", Status: "pending"},
{ID: 2, OrderNumber: "DA002", Status: "approved"},
}, 2, nil
},
}
h := handler.NewDeliveryHandler(mock)
router := setupDeliveryRouter(h)
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/api/apply-delivery?page=1&pageSize=10", nil)
router.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Errorf("expected status 200, got %d", w.Code)
}
var resp map[string]interface{}
json.Unmarshal(w.Body.Bytes(), &resp)
if resp["success"] != true {
t.Errorf("expected success true, got %v", resp["success"])
}
}
func TestDeliveryCreateApply_Success(t *testing.T) {
mock := &mockDeliveryService{
createApplyFn: func(e *model.DeliveryApply) error {
e.ID = 1
e.OrderNumber = "DA1234567890"
return nil
},
}
h := handler.NewDeliveryHandler(mock)
router := setupDeliveryRouter(h)
body := `{"blNumber":"BL001","commodity":"燕麦","quantity":100}`
w := httptest.NewRecorder()
req, _ := http.NewRequest("POST", "/api/apply-delivery", bytes.NewReader([]byte(body)))
req.Header.Set("Content-Type", "application/json")
router.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Errorf("expected status 200, got %d", w.Code)
}
}
func TestDeliveryDeleteApply_Success(t *testing.T) {
mock := &mockDeliveryService{
deleteApplyFn: func(id uint) error { return nil },
}
h := handler.NewDeliveryHandler(mock)
router := setupDeliveryRouter(h)
w := httptest.NewRecorder()
req, _ := http.NewRequest("DELETE", "/api/apply-delivery/1", nil)
router.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Errorf("expected status 200, got %d", w.Code)
}
}
func TestDeliveryDeleteApply_NotFound(t *testing.T) {
mock := &mockDeliveryService{
deleteApplyFn: func(id uint) error { return errors.New("not found") },
}
h := handler.NewDeliveryHandler(mock)
router := setupDeliveryRouter(h)
w := httptest.NewRecorder()
req, _ := http.NewRequest("DELETE", "/api/apply-delivery/999", nil)
router.ServeHTTP(w, req)
if w.Code != http.StatusInternalServerError {
t.Errorf("expected status 500, got %d", w.Code)
}
}
// ========== 提货明细 /api/delivery-details ==========
func TestDeliveryListOutbound_Success(t *testing.T) {
mock := &mockDeliveryService{
listOutboundFn: func(page, pageSize int, outboundNumber, blNumber, status string) ([]model.DeliveryOutbound, int64, error) {
return []model.DeliveryOutbound{
{ID: 1, OutboundNumber: "OB001", OutboundStatus: "completed"},
}, 1, nil
},
}
h := handler.NewDeliveryHandler(mock)
router := setupDeliveryRouter(h)
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/api/delivery-details?page=1&pageSize=10", nil)
router.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Errorf("expected status 200, got %d", w.Code)
}
}
func TestDeliveryCreateOutbound_Success(t *testing.T) {
mock := &mockDeliveryService{
createOutboundFn: func(e *model.DeliveryOutbound) error {
e.ID = 1
e.OutboundNumber = "OB1234567890"
return nil
},
}
h := handler.NewDeliveryHandler(mock)
router := setupDeliveryRouter(h)
body := `{"blNumber":"BL001","warehouse":"A库","quantity":50}`
w := httptest.NewRecorder()
req, _ := http.NewRequest("POST", "/api/delivery-details", bytes.NewReader([]byte(body)))
req.Header.Set("Content-Type", "application/json")
router.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Errorf("expected status 200, got %d", w.Code)
}
}
func TestDeliveryDeleteOutbound_Success(t *testing.T) {
mock := &mockDeliveryService{
deleteOutboundFn: func(id uint) error { return nil },
}
h := handler.NewDeliveryHandler(mock)
router := setupDeliveryRouter(h)
w := httptest.NewRecorder()
req, _ := http.NewRequest("DELETE", "/api/delivery-details/1", nil)
router.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Errorf("expected status 200, got %d", w.Code)
}
}
// ========== 库存 /api/inventory ==========
func TestDeliveryListWarehouses_Success(t *testing.T) {
mock := &mockDeliveryService{
listWarehousesFn: func() ([]model.Warehouse, error) {
return []model.Warehouse{
{ID: 1, Name: "A库", Status: "active"},
{ID: 2, Name: "B库", Status: "active"},
}, nil
},
}
h := handler.NewDeliveryHandler(mock)
router := setupDeliveryRouter(h)
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/api/inventory/warehouses", nil)
router.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Errorf("expected status 200, got %d", w.Code)
}
}
func TestDeliveryCreateWarehouse_Success(t *testing.T) {
mock := &mockDeliveryService{
createWarehouseFn: func(e *model.Warehouse) error {
e.ID = 1
return nil
},
}
h := handler.NewDeliveryHandler(mock)
router := setupDeliveryRouter(h)
body := `{"name":"C库","location":"广州"}`
w := httptest.NewRecorder()
req, _ := http.NewRequest("POST", "/api/inventory/warehouses", bytes.NewReader([]byte(body)))
req.Header.Set("Content-Type", "application/json")
router.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Errorf("expected status 200, got %d", w.Code)
}
}
func TestDeliveryDeleteWarehouse_Success(t *testing.T) {
mock := &mockDeliveryService{
deleteWarehouseFn: func(id uint) error { return nil },
}
h := handler.NewDeliveryHandler(mock)
router := setupDeliveryRouter(h)
w := httptest.NewRecorder()
req, _ := http.NewRequest("DELETE", "/api/inventory/warehouses/1", nil)
router.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Errorf("expected status 200, got %d", w.Code)
}
}
func TestDeliveryCreateInbound_Success(t *testing.T) {
mock := &mockDeliveryService{
createInboundFn: func(e *model.InventoryInbound) error {
e.ID = 1
e.InboundNumber = "IN1234567890"
return nil
},
}
h := handler.NewDeliveryHandler(mock)
router := setupDeliveryRouter(h)
body := `{"warehouse":"A库","commodity":"燕麦","inboundWeight":1000}`
w := httptest.NewRecorder()
req, _ := http.NewRequest("POST", "/api/inventory/inbound", bytes.NewReader([]byte(body)))
req.Header.Set("Content-Type", "application/json")
router.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Errorf("expected status 200, got %d", w.Code)
}
}
// ========== 货权转移 /api/ownership-transfer ==========
func TestDeliveryListOwnership_Success(t *testing.T) {
mock := &mockDeliveryService{
listOwnershipFn: func(page, pageSize int, transferNumber, blNumber, status string) ([]model.OwnershipTransfer, int64, error) {
return []model.OwnershipTransfer{
{ID: 1, TransferNumber: "OT001", Status: "draft"},
}, 1, nil
},
}
h := handler.NewDeliveryHandler(mock)
router := setupDeliveryRouter(h)
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/api/ownership-transfer?page=1&pageSize=10", nil)
router.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Errorf("expected status 200, got %d", w.Code)
}
}
func TestDeliveryDeleteOwnership_Success(t *testing.T) {
mock := &mockDeliveryService{
deleteOwnershipFn: func(id uint) error { return nil },
}
h := handler.NewDeliveryHandler(mock)
router := setupDeliveryRouter(h)
w := httptest.NewRecorder()
req, _ := http.NewRequest("DELETE", "/api/ownership-transfer/1", nil)
router.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Errorf("expected status 200, got %d", w.Code)
}
}