From 69bdc50b3e34baf746ca0d73691af5f085b9b65a Mon Sep 17 00:00:00 2001 From: huang <1724659546@qq.com> Date: Sun, 14 Sep 2025 13:36:41 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=86=E7=8A=B6=E6=80=81=E7=A0=81=E6=94=B9?= =?UTF-8?q?=E6=88=90=E8=87=AA=E5=AE=9A=E4=B9=89=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../device/device_controller_test.go | 52 +++++++++---------- .../controller/user/user_controller_test.go | 47 ++++++++++------- 2 files changed, 53 insertions(+), 46 deletions(-) diff --git a/internal/app/controller/device/device_controller_test.go b/internal/app/controller/device/device_controller_test.go index 47d3ced..5999df4 100644 --- a/internal/app/controller/device/device_controller_test.go +++ b/internal/app/controller/device/device_controller_test.go @@ -203,7 +203,7 @@ func TestCreateDevice(t *testing.T) { }).Once() }, expectedStatus: http.StatusOK, - expectedCode: http.StatusCreated, + expectedCode: controller.CodeCreated, expectedMessage: "设备创建成功", expectedDataFunc: func(data interface{}) bool { dataMap, ok := data.(map[string]interface{}) @@ -236,7 +236,7 @@ func TestCreateDevice(t *testing.T) { }).Once() }, expectedStatus: http.StatusOK, - expectedCode: http.StatusCreated, + expectedCode: controller.CodeCreated, expectedMessage: "设备创建成功", expectedDataFunc: func(data interface{}) bool { dataMap, ok := data.(map[string]interface{}) @@ -260,7 +260,7 @@ func TestCreateDevice(t *testing.T) { }, mockRepoSetup: func(m *MockDeviceRepository) {}, expectedStatus: http.StatusOK, - expectedCode: http.StatusBadRequest, + expectedCode: controller.CodeBadRequest, expectedMessage: "Key: 'CreateDeviceRequest.Name' Error:Field validation for 'Name' failed on the 'required' tag", expectedDataFunc: func(data interface{}) bool { return data == nil }, }, @@ -275,7 +275,7 @@ func TestCreateDevice(t *testing.T) { m.On("Create", mock.Anything).Return(errors.New("db error")).Once() }, expectedStatus: http.StatusOK, - expectedCode: http.StatusInternalServerError, + expectedCode: controller.CodeInternalError, expectedMessage: "创建设备失败", expectedDataFunc: func(data interface{}) bool { return data == nil }, }, @@ -299,9 +299,9 @@ func TestCreateDevice(t *testing.T) { assert.True(t, bytes.Equal(dev.Properties, expectedProperties), "Properties should match") }).Once() }, - expectedStatus: http.StatusOK, // HTTP status is 200 OK for business errors - expectedCode: http.StatusInternalServerError, // Business code for internal server error - expectedMessage: "创建设备失败", // The message returned by the controller + expectedStatus: http.StatusOK, // HTTP status is 200 OK for business errors + expectedCode: controller.CodeInternalError, // Business code for internal server error + expectedMessage: "创建设备失败", // The message returned by the controller expectedDataFunc: func(data interface{}) bool { return data == nil }, }, } @@ -338,7 +338,7 @@ func TestGetDevice(t *testing.T) { }, nil).Once() }, expectedStatus: http.StatusOK, - expectedCode: http.StatusOK, + expectedCode: controller.CodeSuccess, expectedMessage: "获取设备信息成功", expectedDataFunc: func(data interface{}) bool { dataMap, ok := data.(map[string]interface{}) @@ -359,7 +359,7 @@ func TestGetDevice(t *testing.T) { m.On("FindByIDString", "999").Return(nil, gorm.ErrRecordNotFound).Once() }, expectedStatus: http.StatusOK, - expectedCode: http.StatusNotFound, + expectedCode: controller.CodeNotFound, expectedMessage: "设备未找到", expectedDataFunc: func(data interface{}) bool { return data == nil }, }, @@ -372,7 +372,7 @@ func TestGetDevice(t *testing.T) { m.On("FindByIDString", "abc").Return(nil, errors.New("无效的设备ID格式")).Once() }, expectedStatus: http.StatusOK, - expectedCode: http.StatusBadRequest, + expectedCode: controller.CodeBadRequest, expectedMessage: "无效的设备ID格式", expectedDataFunc: func(data interface{}) bool { return data == nil }, }, @@ -385,7 +385,7 @@ func TestGetDevice(t *testing.T) { m.On("FindByIDString", "1").Return(nil, errors.New("db error")).Once() }, expectedStatus: http.StatusOK, - expectedCode: http.StatusInternalServerError, + expectedCode: controller.CodeInternalError, expectedMessage: "获取设备信息失败", expectedDataFunc: func(data interface{}) bool { return data == nil }, }, @@ -413,7 +413,7 @@ func TestListDevices(t *testing.T) { m.On("ListAll").Return([]*models.Device{}, nil).Once() }, expectedStatus: http.StatusOK, - expectedCode: http.StatusOK, + expectedCode: controller.CodeSuccess, expectedMessage: "获取设备列表成功", expectedDataFunc: func(data interface{}) bool { s, ok := data.([]interface{}) @@ -450,7 +450,7 @@ func TestListDevices(t *testing.T) { }, nil).Once() }, expectedStatus: http.StatusOK, - expectedCode: http.StatusOK, + expectedCode: controller.CodeSuccess, expectedMessage: "获取设备列表成功", expectedDataFunc: func(data interface{}) bool { dataList, ok := data.([]interface{}) @@ -483,7 +483,7 @@ func TestListDevices(t *testing.T) { m.On("ListAll").Return(nil, errors.New("db error")).Once() }, expectedStatus: http.StatusOK, - expectedCode: http.StatusInternalServerError, + expectedCode: controller.CodeInternalError, expectedMessage: "获取设备列表失败", expectedDataFunc: func(data interface{}) bool { return data == nil }, }, @@ -529,7 +529,7 @@ func TestUpdateDevice(t *testing.T) { m.On("Update", mock.AnythingOfType("*models.Device")).Return(nil).Once() }, expectedStatus: http.StatusOK, - expectedCode: http.StatusOK, + expectedCode: controller.CodeSuccess, expectedMessage: "设备更新成功", expectedDataFunc: func(data interface{}) bool { dataMap, ok := data.(map[string]interface{}) @@ -555,7 +555,7 @@ func TestUpdateDevice(t *testing.T) { m.On("FindByIDString", "1").Return(&models.Device{Model: gorm.Model{ID: 1}}, nil).Once() }, expectedStatus: http.StatusOK, - expectedCode: http.StatusBadRequest, + expectedCode: controller.CodeBadRequest, expectedMessage: "Key: 'UpdateDeviceRequest.Name' Error:Field validation for 'Name' failed on the 'required' tag", expectedDataFunc: func(data interface{}) bool { return data == nil }, }, @@ -570,7 +570,7 @@ func TestUpdateDevice(t *testing.T) { m.On("FindByIDString", "999").Return(nil, gorm.ErrRecordNotFound).Once() }, expectedStatus: http.StatusOK, - expectedCode: http.StatusNotFound, + expectedCode: controller.CodeNotFound, expectedMessage: "设备未找到", expectedDataFunc: func(data interface{}) bool { return data == nil }, }, @@ -585,7 +585,7 @@ func TestUpdateDevice(t *testing.T) { m.On("FindByIDString", "abc").Return(nil, errors.New("无效的设备ID格式")).Once() }, expectedStatus: http.StatusOK, - expectedCode: http.StatusBadRequest, + expectedCode: controller.CodeBadRequest, expectedMessage: "无效的设备ID格式", expectedDataFunc: func(data interface{}) bool { return data == nil }, }, @@ -601,7 +601,7 @@ func TestUpdateDevice(t *testing.T) { m.On("Update", mock.AnythingOfType("*models.Device")).Return(errors.New("db error")).Once() }, expectedStatus: http.StatusOK, - expectedCode: http.StatusInternalServerError, + expectedCode: controller.CodeInternalError, expectedMessage: "更新设备失败", expectedDataFunc: func(data interface{}) bool { return data == nil }, }, @@ -628,8 +628,8 @@ func TestUpdateDevice(t *testing.T) { }).Once() }, expectedStatus: http.StatusOK, - expectedCode: http.StatusInternalServerError, // Expected to be internal server error due to DB error - expectedMessage: "更新设备失败", // The message returned by the controller + expectedCode: controller.CodeInternalError, // Expected to be internal server error due to DB error + expectedMessage: "更新设备失败", // The message returned by the controller expectedDataFunc: func(data interface{}) bool { return data == nil }, }, // 新增:成功更新设备的ParentID @@ -664,7 +664,7 @@ func TestUpdateDevice(t *testing.T) { })).Return(nil).Once() }, expectedStatus: http.StatusOK, - expectedCode: http.StatusOK, + expectedCode: controller.CodeSuccess, expectedMessage: "设备更新成功", expectedDataFunc: func(data interface{}) bool { dataMap, ok := data.(map[string]interface{}) @@ -700,7 +700,7 @@ func TestDeleteDevice(t *testing.T) { m.On("Delete", uint(1)).Return(nil).Once() }, expectedStatus: http.StatusOK, - expectedCode: http.StatusOK, + expectedCode: controller.CodeSuccess, expectedMessage: "设备删除成功", expectedDataFunc: func(data interface{}) bool { return data == nil }, }, @@ -711,7 +711,7 @@ func TestDeleteDevice(t *testing.T) { paramID: "abc", mockRepoSetup: func(m *MockDeviceRepository) {}, expectedStatus: http.StatusOK, - expectedCode: http.StatusBadRequest, + expectedCode: controller.CodeBadRequest, expectedMessage: "无效的设备ID格式", expectedDataFunc: func(data interface{}) bool { return data == nil }, }, @@ -724,7 +724,7 @@ func TestDeleteDevice(t *testing.T) { m.On("Delete", uint(1)).Return(errors.New("db error")).Once() }, expectedStatus: http.StatusOK, - expectedCode: http.StatusInternalServerError, + expectedCode: controller.CodeInternalError, expectedMessage: "删除设备失败", expectedDataFunc: func(data interface{}) bool { return data == nil }, }, @@ -738,7 +738,7 @@ func TestDeleteDevice(t *testing.T) { m.On("Delete", uint(999)).Return(gorm.ErrRecordNotFound).Once() }, expectedStatus: http.StatusOK, - expectedCode: http.StatusInternalServerError, // 当前控制器逻辑会将 ErrRecordNotFound 视为内部错误 + expectedCode: controller.CodeInternalError, // 当前控制器逻辑会将 ErrRecordNotFound 视为内部错误 expectedMessage: "删除设备失败", expectedDataFunc: func(data interface{}) bool { return data == nil }, }, diff --git a/internal/app/controller/user/user_controller_test.go b/internal/app/controller/user/user_controller_test.go index 2f165bc..ccf6db6 100644 --- a/internal/app/controller/user/user_controller_test.go +++ b/internal/app/controller/user/user_controller_test.go @@ -9,6 +9,7 @@ import ( "net/http/httptest" "testing" + "git.huangwc.com/pig/pig-farm-controller/internal/app/controller" "git.huangwc.com/pig/pig-farm-controller/internal/app/controller/user" "git.huangwc.com/pig/pig-farm-controller/internal/app/service/token" "git.huangwc.com/pig/pig-farm-controller/internal/infra/logs" @@ -106,7 +107,7 @@ func TestCreateUser(t *testing.T) { // 在成功创建用户的路径下,FindByUsername 不会被调用,因此这里不需要设置其期望 }, expectedResponse: map[string]interface{}{ - "code": float64(http.StatusCreated), // 修改这里:从 http.StatusOK 改为 http.StatusCreated + "code": float64(controller.CodeCreated), // 修改这里:使用自定义状态码 "message": "用户创建成功", "data": map[string]interface{}{ "username": "testuser", @@ -124,7 +125,7 @@ func TestCreateUser(t *testing.T) { // 不会调用 Create 或 FindByUsername }, expectedResponse: map[string]interface{}{ - "code": float64(http.StatusBadRequest), + "code": float64(controller.CodeBadRequest), "message": "Key: 'CreateUserRequest.Password' Error:Field validation for 'Password' failed on the 'min' tag", "data": nil, }, @@ -138,7 +139,7 @@ func TestCreateUser(t *testing.T) { // 不会调用 Create 或 FindByUsername }, expectedResponse: map[string]interface{}{ - "code": float64(http.StatusBadRequest), + "code": float64(controller.CodeBadRequest), "message": "Key: 'CreateUserRequest.Username' Error:Field validation for 'Username' failed on the 'required' tag", "data": nil, }, @@ -156,7 +157,7 @@ func TestCreateUser(t *testing.T) { m.On("FindByUsername", "existinguser").Return(&models.User{Username: "existinguser"}, nil).Once() }, expectedResponse: map[string]interface{}{ - "code": float64(http.StatusConflict), + "code": float64(controller.CodeConflict), "message": "用户名已存在", "data": nil, }, @@ -174,7 +175,7 @@ func TestCreateUser(t *testing.T) { m.On("FindByUsername", "db_error_user").Return(nil, gorm.ErrRecordNotFound).Once() }, expectedResponse: map[string]interface{}{ - "code": float64(http.StatusInternalServerError), + "code": float64(controller.CodeInternalError), "message": "创建用户失败", "data": nil, }, @@ -200,10 +201,10 @@ func TestCreateUser(t *testing.T) { tt.mockRepoSetup(mockRepo) // 创建控制器实例,使用静默日志器 - controller := user.NewController(mockRepo, silentLogger, nil) // tokenService 在 CreateUser 中未使用,设为 nil + userController := user.NewController(mockRepo, silentLogger, nil) // tokenService 在 CreateUser 中未使用,设为 nil // 调用被测试的方法 - controller.CreateUser(ctx) + userController.CreateUser(ctx) // 解析响应体 var responseBody map[string]interface{} @@ -214,7 +215,7 @@ func TestCreateUser(t *testing.T) { assert.Equal(t, tt.expectedResponse["code"], responseBody["code"]) // 断言响应内容 (除了 code 字段) - if tt.expectedResponse["code"] == float64(http.StatusCreated) { // 修改这里:从 http.StatusOK 改为 http.StatusCreated + if tt.expectedResponse["code"] == float64(controller.CodeCreated) { // 确保 data 字段存在且是 map[string]interface{} 类型 data, ok := responseBody["data"].(map[string]interface{}) assert.True(t, ok, "响应体中的 data 字段应为 map[string]interface{}") @@ -282,7 +283,7 @@ func TestLogin(t *testing.T) { m.On("GenerateToken", uint(1)).Return("mocked_token", nil).Once() }, expectedResponse: map[string]interface{}{ - "code": float64(http.StatusOK), + "code": float64(controller.CodeSuccess), "message": "登录成功", "data": map[string]interface{}{ "username": "loginuser", @@ -300,7 +301,7 @@ func TestLogin(t *testing.T) { mockRepoSetup: func(m *MockUserRepository) {}, mockTokenServiceSetup: func(m *MockTokenService) {}, expectedResponse: map[string]interface{}{ - "code": float64(http.StatusBadRequest), + "code": float64(controller.CodeBadRequest), "message": "Key: 'LoginRequest.Username' Error:Field validation for 'Username' failed on the 'required' tag", "data": nil, }, @@ -314,7 +315,7 @@ func TestLogin(t *testing.T) { mockRepoSetup: func(m *MockUserRepository) {}, mockTokenServiceSetup: func(m *MockTokenService) {}, expectedResponse: map[string]interface{}{ - "code": float64(http.StatusBadRequest), + "code": float64(controller.CodeBadRequest), "message": "Key: 'LoginRequest.Password' Error:Field validation for 'Password' failed on the 'required' tag", "data": nil, }, @@ -330,7 +331,7 @@ func TestLogin(t *testing.T) { }, mockTokenServiceSetup: func(m *MockTokenService) {}, expectedResponse: map[string]interface{}{ - "code": float64(http.StatusUnauthorized), + "code": float64(controller.CodeUnauthorized), "message": "用户名或密码不正确", "data": nil, }, @@ -345,7 +346,7 @@ func TestLogin(t *testing.T) { m.On("FindByUsername", "dberroruser").Return(nil, errors.New("database connection error")).Once() }, mockTokenServiceSetup: func(m *MockTokenService) {}, expectedResponse: map[string]interface{}{ - "code": float64(http.StatusInternalServerError), + "code": float64(controller.CodeInternalError), "message": "登录失败", "data": nil, }, @@ -368,7 +369,7 @@ func TestLogin(t *testing.T) { }, mockTokenServiceSetup: func(m *MockTokenService) {}, expectedResponse: map[string]interface{}{ - "code": float64(http.StatusUnauthorized), + "code": float64(controller.CodeUnauthorized), "message": "用户名或密码不正确", "data": nil, }, @@ -393,7 +394,7 @@ func TestLogin(t *testing.T) { m.On("GenerateToken", uint(1)).Return("", errors.New("jwt error")).Once() }, expectedResponse: map[string]interface{}{ - "code": float64(http.StatusInternalServerError), + "code": float64(controller.CodeInternalError), "message": "登录失败,无法生成认证信息", "data": nil, }, @@ -421,10 +422,10 @@ func TestLogin(t *testing.T) { tt.mockTokenServiceSetup(mockTokenService) // 创建控制器实例 - controller := user.NewController(mockRepo, silentLogger, mockTokenService) + userController := user.NewController(mockRepo, silentLogger, mockTokenService) // 调用被测试的方法 - controller.Login(ctx) + userController.Login(ctx) // 解析响应体 var responseBody map[string]interface{} @@ -435,9 +436,15 @@ func TestLogin(t *testing.T) { assert.Equal(t, tt.expectedResponse["code"], responseBody["code"]) // 断言响应内容 (除了 code 字段) - if tt.expectedResponse["code"] == float64(http.StatusOK) { - assert.NotNil(t, responseBody["data"].(map[string]interface{})["id"]) - assert.NotNil(t, responseBody["data"].(map[string]interface{})["token"]) + if tt.expectedResponse["code"] == float64(controller.CodeSuccess) { + // 确保 data 字段存在且是 map[string]interface{} 类型 + data, ok := responseBody["data"].(map[string]interface{}) + assert.True(t, ok, "响应体中的 data 字段应为 map[string]interface{}") + + // 验证 id 和 token 存在 + assert.NotNil(t, data["id"]) + assert.NotNil(t, data["token"]) + // 移除 ID 和 Token 字段以便进行通用断言 delete(responseBody["data"].(map[string]interface{}), "id") delete(tt.expectedResponse["data"].(map[string]interface{}), "id")