Compare commits
3 Commits
eb1be3f366
...
b926f7d6a3
| Author | SHA1 | Date | |
|---|---|---|---|
| b926f7d6a3 | |||
| 389c2f9846 | |||
| 55d32dad5f |
@@ -17,8 +17,6 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
"go.uber.org/zap"
|
|
||||||
"go.uber.org/zap/zapcore"
|
|
||||||
"gorm.io/datatypes"
|
"gorm.io/datatypes"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
@@ -82,17 +80,6 @@ func (m *MockDeviceRepository) Delete(id uint) error {
|
|||||||
return args.Error(0)
|
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 结构体定义了所有测试用例的通用参数
|
// testCase 结构体定义了所有测试用例的通用参数
|
||||||
type testCase struct {
|
type testCase struct {
|
||||||
name string
|
name string
|
||||||
@@ -309,7 +296,7 @@ func TestCreateDevice(t *testing.T) {
|
|||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
runTest(t, tc, func(ctx *gin.Context, repo *MockDeviceRepository) {
|
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 {
|
for _, tc := range tests {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
runTest(t, tc, func(ctx *gin.Context, repo *MockDeviceRepository) {
|
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 {
|
for _, tc := range tests {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
runTest(t, tc, func(ctx *gin.Context, repo *MockDeviceRepository) {
|
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 {
|
for _, tc := range tests {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
runTest(t, tc, func(ctx *gin.Context, repo *MockDeviceRepository) {
|
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 {
|
for _, tc := range tests {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
runTest(t, tc, func(ctx *gin.Context, repo *MockDeviceRepository) {
|
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代表创建成功"
|
// @Success 200 {object} controller.Response{data=plan.PlanResponse} "业务码为201代表创建成功"
|
||||||
// @Failure 200 {object} controller.Response "业务失败,具体错误码和信息见响应体(例如400, 500)"
|
// @Failure 200 {object} controller.Response "业务失败,具体错误码和信息见响应体(例如400, 500)"
|
||||||
// @Router /plans [post]
|
// @Router /plans [post]
|
||||||
func (pc *Controller) CreatePlan(c *gin.Context) {
|
func (c *Controller) CreatePlan(ctx *gin.Context) {
|
||||||
// 占位符:此处应调用服务层或仓库层来创建计划
|
var req CreatePlanRequest
|
||||||
pc.logger.Infof("收到创建计划请求 (占位符)")
|
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||||||
controller.SendResponse(c, controller.CodeCreated, "创建计划接口占位符", PlanResponse{ID: 0, Name: "占位计划"})
|
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
|
// 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/gin-gonic/gin"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
"go.uber.org/zap"
|
|
||||||
"go.uber.org/zap/zapcore"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -77,13 +75,7 @@ func TestCreateUser(t *testing.T) {
|
|||||||
gin.SetMode(gin.TestMode) // 设置 Gin 为测试模式
|
gin.SetMode(gin.TestMode) // 设置 Gin 为测试模式
|
||||||
|
|
||||||
// 创建一个不输出日志的真实 logs.Logger 实例
|
// 创建一个不输出日志的真实 logs.Logger 实例
|
||||||
discardSyncer := zapcore.AddSync(io.Discard)
|
silentLogger := logs.NewSilentLogger()
|
||||||
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}
|
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -248,13 +240,7 @@ func TestLogin(t *testing.T) {
|
|||||||
gin.SetMode(gin.ReleaseMode)
|
gin.SetMode(gin.ReleaseMode)
|
||||||
|
|
||||||
// 创建一个不输出日志的真实 logs.Logger 实例
|
// 创建一个不输出日志的真实 logs.Logger 实例
|
||||||
discardSyncer := zapcore.AddSync(io.Discard)
|
silentLogger := logs.NewSilentLogger()
|
||||||
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}
|
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package logs
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"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")
|
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