Compare commits
	
		
			3 Commits
		
	
	
		
			eb1be3f366
			...
			b926f7d6a3
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| b926f7d6a3 | |||
| 389c2f9846 | |||
| 55d32dad5f | 
@@ -17,8 +17,6 @@ import (
 | 
			
		||||
	"github.com/gin-gonic/gin"
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
	"github.com/stretchr/testify/mock"
 | 
			
		||||
	"go.uber.org/zap"
 | 
			
		||||
	"go.uber.org/zap/zapcore"
 | 
			
		||||
	"gorm.io/datatypes"
 | 
			
		||||
	"gorm.io/gorm"
 | 
			
		||||
)
 | 
			
		||||
@@ -82,17 +80,6 @@ func (m *MockDeviceRepository) Delete(id uint) error {
 | 
			
		||||
	return args.Error(0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getSilentLogger 创建一个不输出日志的 logs.Logger 实例,用于测试
 | 
			
		||||
func getSilentLogger() *logs.Logger {
 | 
			
		||||
	discardSyncer := zapcore.AddSync(io.Discard)
 | 
			
		||||
	encoderConfig := zap.NewProductionEncoderConfig()
 | 
			
		||||
	encoder := zapcore.NewConsoleEncoder(encoderConfig)
 | 
			
		||||
	core := zapcore.NewCore(encoder, discardSyncer, zap.DebugLevel)
 | 
			
		||||
	zapLogger := zap.New(core)
 | 
			
		||||
	sugaredLogger := zapLogger.Sugar()
 | 
			
		||||
	return &logs.Logger{SugaredLogger: sugaredLogger}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// testCase 结构体定义了所有测试用例的通用参数
 | 
			
		||||
type testCase struct {
 | 
			
		||||
	name             string
 | 
			
		||||
@@ -309,7 +296,7 @@ func TestCreateDevice(t *testing.T) {
 | 
			
		||||
	for _, tc := range tests {
 | 
			
		||||
		t.Run(tc.name, func(t *testing.T) {
 | 
			
		||||
			runTest(t, tc, func(ctx *gin.Context, repo *MockDeviceRepository) {
 | 
			
		||||
				device.NewController(repo, getSilentLogger()).CreateDevice(ctx)
 | 
			
		||||
				device.NewController(repo, logs.NewSilentLogger()).CreateDevice(ctx)
 | 
			
		||||
			})
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
@@ -394,7 +381,7 @@ func TestGetDevice(t *testing.T) {
 | 
			
		||||
	for _, tc := range tests {
 | 
			
		||||
		t.Run(tc.name, func(t *testing.T) {
 | 
			
		||||
			runTest(t, tc, func(ctx *gin.Context, repo *MockDeviceRepository) {
 | 
			
		||||
				device.NewController(repo, getSilentLogger()).GetDevice(ctx)
 | 
			
		||||
				device.NewController(repo, logs.NewSilentLogger()).GetDevice(ctx)
 | 
			
		||||
			})
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
@@ -492,7 +479,7 @@ func TestListDevices(t *testing.T) {
 | 
			
		||||
	for _, tc := range tests {
 | 
			
		||||
		t.Run(tc.name, func(t *testing.T) {
 | 
			
		||||
			runTest(t, tc, func(ctx *gin.Context, repo *MockDeviceRepository) {
 | 
			
		||||
				device.NewController(repo, getSilentLogger()).ListDevices(ctx)
 | 
			
		||||
				device.NewController(repo, logs.NewSilentLogger()).ListDevices(ctx)
 | 
			
		||||
			})
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
@@ -681,7 +668,7 @@ func TestUpdateDevice(t *testing.T) {
 | 
			
		||||
	for _, tc := range tests {
 | 
			
		||||
		t.Run(tc.name, func(t *testing.T) {
 | 
			
		||||
			runTest(t, tc, func(ctx *gin.Context, repo *MockDeviceRepository) {
 | 
			
		||||
				device.NewController(repo, getSilentLogger()).UpdateDevice(ctx)
 | 
			
		||||
				device.NewController(repo, logs.NewSilentLogger()).UpdateDevice(ctx)
 | 
			
		||||
			})
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
@@ -747,7 +734,7 @@ func TestDeleteDevice(t *testing.T) {
 | 
			
		||||
	for _, tc := range tests {
 | 
			
		||||
		t.Run(tc.name, func(t *testing.T) {
 | 
			
		||||
			runTest(t, tc, func(ctx *gin.Context, repo *MockDeviceRepository) {
 | 
			
		||||
				device.NewController(repo, getSilentLogger()).DeleteDevice(ctx)
 | 
			
		||||
				device.NewController(repo, logs.NewSilentLogger()).DeleteDevice(ctx)
 | 
			
		||||
			})
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -107,10 +107,31 @@ func NewController(logger *logs.Logger, planRepo repository.PlanRepository) *Con
 | 
			
		||||
// @Success      200 {object} controller.Response{data=plan.PlanResponse} "业务码为201代表创建成功"
 | 
			
		||||
// @Failure      200 {object} controller.Response "业务失败,具体错误码和信息见响应体(例如400, 500)"
 | 
			
		||||
// @Router       /plans [post]
 | 
			
		||||
func (pc *Controller) CreatePlan(c *gin.Context) {
 | 
			
		||||
	// 占位符:此处应调用服务层或仓库层来创建计划
 | 
			
		||||
	pc.logger.Infof("收到创建计划请求 (占位符)")
 | 
			
		||||
	controller.SendResponse(c, controller.CodeCreated, "创建计划接口占位符", PlanResponse{ID: 0, Name: "占位计划"})
 | 
			
		||||
func (c *Controller) CreatePlan(ctx *gin.Context) {
 | 
			
		||||
	var req CreatePlanRequest
 | 
			
		||||
	if err := ctx.ShouldBindJSON(&req); err != nil {
 | 
			
		||||
		controller.SendErrorResponse(ctx, controller.CodeBadRequest, "无效的请求体: "+err.Error())
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 使用已有的转换函数,它已经包含了验证和重排逻辑
 | 
			
		||||
	planToCreate, err := PlanFromCreateRequest(&req)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		controller.SendErrorResponse(ctx, controller.CodeBadRequest, "计划数据校验失败: "+err.Error())
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 调用仓库方法创建计划
 | 
			
		||||
	if err := c.planRepo.CreatePlan(planToCreate); err != nil {
 | 
			
		||||
		controller.SendErrorResponse(ctx, controller.CodeBadRequest, "创建计划失败: "+err.Error())
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 使用已有的转换函数将创建后的模型转换为响应对象
 | 
			
		||||
	resp := PlanToResponse(planToCreate)
 | 
			
		||||
 | 
			
		||||
	// 使用统一的成功响应函数
 | 
			
		||||
	controller.SendResponse(ctx, controller.CodeCreated, "计划创建成功", resp)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetPlan godoc
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										243
									
								
								internal/app/controller/plan/plan_controller_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										243
									
								
								internal/app/controller/plan/plan_controller_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,243 @@
 | 
			
		||||
package plan
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/http/httptest"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"git.huangwc.com/pig/pig-farm-controller/internal/app/controller"
 | 
			
		||||
	"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
 | 
			
		||||
	"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
 | 
			
		||||
	"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
 | 
			
		||||
	"github.com/gin-gonic/gin"
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// MockPlanRepository 是 repository.PlanRepository 的一个模拟实现,用于测试
 | 
			
		||||
type MockPlanRepository struct {
 | 
			
		||||
	CreatePlanFunc func(plan *models.Plan) error
 | 
			
		||||
	// ... 可以根据需要模拟其他接口方法
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *MockPlanRepository) ListBasicPlans() ([]models.Plan, error) {
 | 
			
		||||
	panic("implement me")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *MockPlanRepository) GetBasicPlanByID(id uint) (*models.Plan, error) {
 | 
			
		||||
	panic("implement me")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *MockPlanRepository) GetPlanByID(id uint) (*models.Plan, error) {
 | 
			
		||||
	panic("implement me")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *MockPlanRepository) CreatePlan(plan *models.Plan) error {
 | 
			
		||||
	if m.CreatePlanFunc != nil {
 | 
			
		||||
		return m.CreatePlanFunc(plan)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *MockPlanRepository) UpdatePlan(plan *models.Plan) error {
 | 
			
		||||
	panic("implement me")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *MockPlanRepository) DeletePlan(id uint) error {
 | 
			
		||||
	panic("implement me")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// setupTestRouter 创建一个用于测试的 gin 引擎和控制器实例
 | 
			
		||||
func setupTestRouter(repo repository.PlanRepository) (*gin.Engine, *Controller) {
 | 
			
		||||
	gin.SetMode(gin.TestMode)
 | 
			
		||||
	router := gin.Default()
 | 
			
		||||
	planController := NewController(logs.NewSilentLogger(), repo)
 | 
			
		||||
	router.POST("/plans", planController.CreatePlan)
 | 
			
		||||
	return router, planController
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestController_CreatePlan(t *testing.T) {
 | 
			
		||||
	t.Run("成功-创建包含任务的计划", func(t *testing.T) {
 | 
			
		||||
		// Arrange
 | 
			
		||||
		mockRepo := &MockPlanRepository{
 | 
			
		||||
			CreatePlanFunc: func(plan *models.Plan) error {
 | 
			
		||||
				// 模拟 GORM 回填 ID
 | 
			
		||||
				plan.ID = 1
 | 
			
		||||
				for i := range plan.Tasks {
 | 
			
		||||
					plan.Tasks[i].ID = uint(i + 1)
 | 
			
		||||
					plan.Tasks[i].PlanID = plan.ID
 | 
			
		||||
				}
 | 
			
		||||
				return nil
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
		router, _ := setupTestRouter(mockRepo)
 | 
			
		||||
 | 
			
		||||
		reqBody := CreatePlanRequest{
 | 
			
		||||
			Name:          "Test Plan with Tasks",
 | 
			
		||||
			ExecutionType: models.PlanExecutionTypeManual,
 | 
			
		||||
			ContentType:   models.PlanContentTypeTasks,
 | 
			
		||||
			Tasks: []TaskRequest{
 | 
			
		||||
				{Name: "Task 1", ExecutionOrder: 1, Type: models.TaskTypeWaiting},
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
		bodyBytes, _ := json.Marshal(reqBody)
 | 
			
		||||
 | 
			
		||||
		req, _ := http.NewRequest(http.MethodPost, "/plans", bytes.NewBuffer(bodyBytes))
 | 
			
		||||
		req.Header.Set("Content-Type", "application/json")
 | 
			
		||||
		w := httptest.NewRecorder()
 | 
			
		||||
 | 
			
		||||
		// Act
 | 
			
		||||
		router.ServeHTTP(w, req)
 | 
			
		||||
 | 
			
		||||
		// Assert
 | 
			
		||||
		assert.Equal(t, http.StatusOK, w.Code)
 | 
			
		||||
 | 
			
		||||
		var resp controller.Response
 | 
			
		||||
		err := json.Unmarshal(w.Body.Bytes(), &resp)
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		assert.Equal(t, controller.CodeCreated, resp.Code)
 | 
			
		||||
		assert.Equal(t, "计划创建成功", resp.Message)
 | 
			
		||||
 | 
			
		||||
		// 验证 Data 部分
 | 
			
		||||
		dataMap, ok := resp.Data.(map[string]interface{})
 | 
			
		||||
		assert.True(t, ok)
 | 
			
		||||
		assert.Equal(t, float64(1), dataMap["id"])
 | 
			
		||||
		assert.Equal(t, "Test Plan with Tasks", dataMap["name"])
 | 
			
		||||
		tasks, ok := dataMap["tasks"].([]interface{})
 | 
			
		||||
		assert.True(t, ok)
 | 
			
		||||
		assert.Len(t, tasks, 1)
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	t.Run("失败-无效的请求体", func(t *testing.T) {
 | 
			
		||||
		// Arrange
 | 
			
		||||
		mockRepo := &MockPlanRepository{}
 | 
			
		||||
		router, _ := setupTestRouter(mockRepo)
 | 
			
		||||
 | 
			
		||||
		req, _ := http.NewRequest(http.MethodPost, "/plans", bytes.NewBufferString("{invalid json"))
 | 
			
		||||
		req.Header.Set("Content-Type", "application/json")
 | 
			
		||||
		w := httptest.NewRecorder()
 | 
			
		||||
 | 
			
		||||
		// Act
 | 
			
		||||
		router.ServeHTTP(w, req)
 | 
			
		||||
 | 
			
		||||
		// Assert
 | 
			
		||||
		assert.Equal(t, http.StatusOK, w.Code)
 | 
			
		||||
 | 
			
		||||
		var resp controller.Response
 | 
			
		||||
		err := json.Unmarshal(w.Body.Bytes(), &resp)
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		assert.Equal(t, controller.CodeBadRequest, resp.Code)
 | 
			
		||||
		assert.Contains(t, resp.Message, "无效的请求体")
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	t.Run("失败-转换器业务校验失败", func(t *testing.T) {
 | 
			
		||||
		// Arrange
 | 
			
		||||
		mockRepo := &MockPlanRepository{}
 | 
			
		||||
		router, _ := setupTestRouter(mockRepo)
 | 
			
		||||
 | 
			
		||||
		// 创建一个带有重复执行顺序的请求,这将导致 PlanFromCreateRequest 返回错误
 | 
			
		||||
		reqBody := CreatePlanRequest{
 | 
			
		||||
			Name:          "Duplicate Order Plan",
 | 
			
		||||
			ExecutionType: models.PlanExecutionTypeManual,
 | 
			
		||||
			ContentType:   models.PlanContentTypeTasks,
 | 
			
		||||
			Tasks: []TaskRequest{
 | 
			
		||||
				{Name: "Task 1", ExecutionOrder: 1},
 | 
			
		||||
				{Name: "Task 2", ExecutionOrder: 1}, // 重复
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
		bodyBytes, _ := json.Marshal(reqBody)
 | 
			
		||||
 | 
			
		||||
		req, _ := http.NewRequest(http.MethodPost, "/plans", bytes.NewBuffer(bodyBytes))
 | 
			
		||||
		req.Header.Set("Content-Type", "application/json")
 | 
			
		||||
		w := httptest.NewRecorder()
 | 
			
		||||
 | 
			
		||||
		// Act
 | 
			
		||||
		router.ServeHTTP(w, req)
 | 
			
		||||
 | 
			
		||||
		// Assert
 | 
			
		||||
		assert.Equal(t, http.StatusOK, w.Code)
 | 
			
		||||
 | 
			
		||||
		var resp controller.Response
 | 
			
		||||
		err := json.Unmarshal(w.Body.Bytes(), &resp)
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		assert.Equal(t, controller.CodeBadRequest, resp.Code)
 | 
			
		||||
		assert.Contains(t, resp.Message, "计划数据校验失败")
 | 
			
		||||
		assert.Contains(t, resp.Message, "任务执行顺序重复")
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	t.Run("失败-仓库层业务错误", func(t *testing.T) {
 | 
			
		||||
		// Arrange
 | 
			
		||||
		mockRepo := &MockPlanRepository{
 | 
			
		||||
			CreatePlanFunc: func(plan *models.Plan) error {
 | 
			
		||||
				return repository.ErrNodeDoesNotExist // 模拟仓库层返回的业务错误
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
		router, _ := setupTestRouter(mockRepo)
 | 
			
		||||
 | 
			
		||||
		reqBody := CreatePlanRequest{
 | 
			
		||||
			Name:          "Plan with non-existent sub-plan",
 | 
			
		||||
			ExecutionType: models.PlanExecutionTypeManual,
 | 
			
		||||
			ContentType:   models.PlanContentTypeSubPlans,
 | 
			
		||||
			SubPlanIDs:    []uint{999}, // 假设这个ID不存在
 | 
			
		||||
		}
 | 
			
		||||
		bodyBytes, _ := json.Marshal(reqBody)
 | 
			
		||||
 | 
			
		||||
		req, _ := http.NewRequest(http.MethodPost, "/plans", bytes.NewBuffer(bodyBytes))
 | 
			
		||||
		req.Header.Set("Content-Type", "application/json")
 | 
			
		||||
		w := httptest.NewRecorder()
 | 
			
		||||
 | 
			
		||||
		// Act
 | 
			
		||||
		router.ServeHTTP(w, req)
 | 
			
		||||
 | 
			
		||||
		// Assert
 | 
			
		||||
		assert.Equal(t, http.StatusOK, w.Code)
 | 
			
		||||
 | 
			
		||||
		var resp controller.Response
 | 
			
		||||
		err := json.Unmarshal(w.Body.Bytes(), &resp)
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		assert.Equal(t, controller.CodeBadRequest, resp.Code)
 | 
			
		||||
		assert.Equal(t, "创建计划失败: "+repository.ErrNodeDoesNotExist.Error(), resp.Message)
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	t.Run("失败-仓库层内部错误", func(t *testing.T) {
 | 
			
		||||
		// Arrange
 | 
			
		||||
		internalErr := errors.New("database connection lost")
 | 
			
		||||
		mockRepo := &MockPlanRepository{
 | 
			
		||||
			CreatePlanFunc: func(plan *models.Plan) error {
 | 
			
		||||
				return internalErr // 模拟一个未知的内部错误
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
		router, _ := setupTestRouter(mockRepo)
 | 
			
		||||
 | 
			
		||||
		reqBody := CreatePlanRequest{
 | 
			
		||||
			Name:          "Test Plan",
 | 
			
		||||
			ExecutionType: models.PlanExecutionTypeManual,
 | 
			
		||||
			ContentType:   models.PlanContentTypeTasks,
 | 
			
		||||
			Tasks:         []TaskRequest{},
 | 
			
		||||
		}
 | 
			
		||||
		bodyBytes, _ := json.Marshal(reqBody)
 | 
			
		||||
 | 
			
		||||
		req, _ := http.NewRequest(http.MethodPost, "/plans", bytes.NewBuffer(bodyBytes))
 | 
			
		||||
		req.Header.Set("Content-Type", "application/json")
 | 
			
		||||
		w := httptest.NewRecorder()
 | 
			
		||||
 | 
			
		||||
		// Act
 | 
			
		||||
		router.ServeHTTP(w, req)
 | 
			
		||||
 | 
			
		||||
		// Assert
 | 
			
		||||
		assert.Equal(t, http.StatusOK, w.Code)
 | 
			
		||||
 | 
			
		||||
		var resp controller.Response
 | 
			
		||||
		err := json.Unmarshal(w.Body.Bytes(), &resp)
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
		assert.Equal(t, controller.CodeBadRequest, resp.Code)
 | 
			
		||||
		assert.Equal(t, "创建计划失败: "+internalErr.Error(), resp.Message)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
@@ -17,8 +17,6 @@ import (
 | 
			
		||||
	"github.com/gin-gonic/gin"
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
	"github.com/stretchr/testify/mock"
 | 
			
		||||
	"go.uber.org/zap"
 | 
			
		||||
	"go.uber.org/zap/zapcore"
 | 
			
		||||
	"gorm.io/gorm"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -77,13 +75,7 @@ func TestCreateUser(t *testing.T) {
 | 
			
		||||
	gin.SetMode(gin.TestMode) // 设置 Gin 为测试模式
 | 
			
		||||
 | 
			
		||||
	// 创建一个不输出日志的真实 logs.Logger 实例
 | 
			
		||||
	discardSyncer := zapcore.AddSync(io.Discard)
 | 
			
		||||
	encoderConfig := zap.NewProductionEncoderConfig()
 | 
			
		||||
	encoder := zapcore.NewConsoleEncoder(encoderConfig)
 | 
			
		||||
	core := zapcore.NewCore(encoder, discardSyncer, zap.DebugLevel) // 设置为 DebugLevel 以确保所有日志都被处理(并丢弃)
 | 
			
		||||
	zapLogger := zap.New(core)
 | 
			
		||||
	sugaredLogger := zapLogger.Sugar()
 | 
			
		||||
	silentLogger := &logs.Logger{SugaredLogger: sugaredLogger}
 | 
			
		||||
	silentLogger := logs.NewSilentLogger()
 | 
			
		||||
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name             string
 | 
			
		||||
@@ -248,13 +240,7 @@ func TestLogin(t *testing.T) {
 | 
			
		||||
	gin.SetMode(gin.ReleaseMode)
 | 
			
		||||
 | 
			
		||||
	// 创建一个不输出日志的真实 logs.Logger 实例
 | 
			
		||||
	discardSyncer := zapcore.AddSync(io.Discard)
 | 
			
		||||
	encoderConfig := zap.NewProductionEncoderConfig()
 | 
			
		||||
	encoder := zapcore.NewConsoleEncoder(encoderConfig)
 | 
			
		||||
	core := zapcore.NewCore(encoder, discardSyncer, zap.DebugLevel) // 设置为 DebugLevel 以确保所有日志都被处理(并丢弃)
 | 
			
		||||
	zapLogger := zap.New(core)
 | 
			
		||||
	sugaredLogger := zapLogger.Sugar()
 | 
			
		||||
	silentLogger := &logs.Logger{SugaredLogger: sugaredLogger}
 | 
			
		||||
	silentLogger := logs.NewSilentLogger()
 | 
			
		||||
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name                  string
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ package logs
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
@@ -163,3 +164,15 @@ func (g *GormLogger) Trace(ctx context.Context, begin time.Time, fc func() (sql
 | 
			
		||||
	g.ZapLogger.With(fields...).Debugf("[GORM] trace")
 | 
			
		||||
	// --- 逻辑修复结束 ---
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewSilentLogger 创建一个不输出任何日志的 Logger 实例, 用于测试中屏蔽日志
 | 
			
		||||
func NewSilentLogger() *Logger {
 | 
			
		||||
	// 创建一个不输出日志的真实 logs.Logger 实例
 | 
			
		||||
	discardSyncer := zapcore.AddSync(io.Discard)
 | 
			
		||||
	encoderConfig := zap.NewProductionEncoderConfig()
 | 
			
		||||
	encoder := zapcore.NewConsoleEncoder(encoderConfig)
 | 
			
		||||
	core := zapcore.NewCore(encoder, discardSyncer, zap.DebugLevel) // 设置为 DebugLevel 以确保所有日志都被处理(并丢弃)
 | 
			
		||||
	zapLogger := zap.New(core)
 | 
			
		||||
	sugaredLogger := zapLogger.Sugar()
 | 
			
		||||
	return &Logger{SugaredLogger: sugaredLogger}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user