Go Fiber创建用户单元测试500错误及类型转换问题修复
创建用户单元测试500错误及nil转换panic解决
问题描述
为创建用户功能编写单元测试时,测试始终返回500 Internal Server Error,实际运行main.go时该功能正常。测试过程中触发interface conversion: interface {} is nil, not map[string]interface {} panic。
相关代码
测试代码(package test)
func setupDB() *sql.DB { var ( username = "root" password = "root" host = "localhost" port = "3306" db_name = "go-fiber-test" ) dns := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=True", username, password, host, port, db_name) db, err := sql.Open("mysql", dns) if err != nil { panic(err) } db.SetMaxIdleConns(10) db.SetMaxOpenConns(100) db.SetConnMaxIdleTime(5 * time.Minute) db.SetConnMaxLifetime(60 * time.Minute) return db } func setupRouter(db *sql.DB) *fiber.App{ validator := validator.New() userRepository := repository.NewUserRepository() userService := service.NewUserService(userRepository, db, validator) userController := controller.NewUserController(userService) router := route.RouteInit(userController) return router } func truncateUsers(db *sql.DB) { db.Exec("TRUNCATE users") } func TestCreateUsersSuccess(t *testing.T) { db := setupDB() router := setupRouter(db) requestBody := strings.NewReader(` { "name": "myname", "email": "mynamecool329@gmail.com", "password": "myname!@#", "address": "Jl. nanananaaana", "phone": "0812388773342" } `) request := httptest.NewRequest("POST", "http://localhost:3000/users/create", requestBody) response, err := router.Test(request) helper.PanicIfError(err) assert.Equal(t, 200, response.StatusCode) body, err := io.ReadAll(response.Body) helper.PanicIfError(err) var responseBody map[string]interface{} err = json.Unmarshal(body, &responseBody) helper.PanicIfError(err) log.Printf("request : %v", request) log.Printf("response : %v", response) log.Printf("response body : %v", response.Body) log.Printf("response body Map: %v", responseBody) assert.Equal(t, 200, int(responseBody["code"].(float64))) assert.Equal(t, "SUCCESS", responseBody["status"]) assert.Equal(t, "myname", responseBody["data"].(map[string]interface{})["name"]) }
路由代码(package route)
func RouteInit(userController controller.UserController) *fiber.App { app := fiber.New() app.Use(func(c *fiber.Ctx) error { defer func() { if err := recover(); err != nil { exception.ErrorHandler(c, err) } }() return c.Next() }) app.Get("/users", middleware.AuthMiddleware, userController.FindAll) app.Get("/users/:userId", userController.FindById) app.Put("/users/:userId", middleware.AuthMiddleware, userController.Update) app.Delete("/users/:userId", middleware.AuthMiddleware, userController.Delete) app.Post("/users/create", userController.Create) app.Post("/login", userController.Login) app.Get("/logout", middleware.AuthMiddleware, userController.Logout) app.Post("/verify", userController.Verify) return app }
错误输出
=== RUN TestCreateUsersSuccess 2023/02/16 11:22:00 request : &{POST http://localhost:3000/users/create HTTP/1.1 1 1 map[Content-Length:[163]] { { "name": "myname", "email": "mynamecool329@gmail.com", "password": "myname!@#", "address": "Jl. nanananaaana", "phone": "0812388773342" } } <nil> 163 [] false localhost:3000 map[] map[] <nil> map[] 192.0.2.1:1234 http://localhost:3000/users/create <nil> <nil> <nil> <nil>} 2023/02/16 11:22:00 response : &{200 OK 200 HTTP/1.1 1 1 map[Content-Length:[57] Content-Type:[application/json] Date:[Thu, 16 Feb 2023 04:22:00 GMT]] 0xc00037b940 57 [] false false map[] 0xc000113d00 <nil>} 2023/02/16 11:22:00 response body : &{0xc00000edb0 <nil> <nil> false false {0 0} true false false <nil>} 2023/02/16 11:22:00 response body Map: map[code:500 data:<nil> status:INTERNAL SERVER ERROR] /home/myname/Documents/Go/go-fiber/unit-test/user/create_test.go:99: Error Trace: /home/myname/Documents/Go/go-fiber/unit-test/user/create_test.go:99 Error: Not equal: expected: 200 actual : 500 Test: TestCreateUsersSuccess /home/myname/Documents/Go/go-fiber/unit-test/user/create_test.go:100: Error Trace: /home/myname/Documents/Go/go-fiber/unit-test/user/create_test.go:100 Error: Not equal: expected: "SUCCESS" actual : "INTERNAL SERVER ERROR" Diff: --- Expected +++ Actual @@ -1 +1 @@ -SUCCESS +INTERNAL SERVER ERROR Test: TestCreateUsersSuccess --- FAIL: TestCreateUsersSuccess (0.00s) panic: interface conversion: interface {} is nil, not map[string]interface {} [recovered] panic: interface conversion: interface {} is nil, not map[string]interface {} goroutine 6 [running]: testing.tRunner.func1.2({0x7e5700, 0xc0003c13b0}) /usr/lib/go-1.18/src/testing/testing.go:1389 +0x24e testing.tRunner.func1() /usr/lib/go-1.18/src/testing/testing.go:1392 +0x39f panic({0x7e5700, 0xc0003c13b0}) /usr/lib/go-1.18/src/runtime/panic.go:838 +0x207 go_fiber/unit-test/user.TestCreateUsersSuccess(0x0?) /home/myname/Documents/Go/go-fiber/unit-test/user/create_test.go:101 +0x425 testing.tRunner(0xc00037c9c0, 0x87f6b8) /usr/lib/go-1.18/src/testing/testing.go:1439 +0x102 created by testing.(*T).Run /usr/lib/go-1.18/src/testing/testing.go:1486 +0x35f FAIL go_fiber/unit-test/user 0.027s
解决方案
1. 补全请求Content-Type头
Fiber需要明确的Content-Type头才能解析JSON请求体,在测试代码中添加该头:
request := httptest.NewRequest("POST", "http://localhost:3000/users/create", requestBody) request.Header.Set("Content-Type", "application/json") // 新增此行
2. 避免nil类型转换panic
当返回500错误时,responseBody["data"]为nil,直接转换会触发panic。修改断言逻辑:
// 替换原有的assert.Equal(t, "myname", responseBody["data"].(map[string]interface{})["name"]) if data, ok := responseBody["data"].(map[string]interface{}); ok && data != nil { assert.Equal(t, "myname", data["name"]) } else { t.Fatal("响应数据为nil或非预期格式") }
3. 验证数据库连接
在setupDB中添加Ping操作,确保数据库连接有效:
db, err := sql.Open("mysql", dns) if err != nil { panic(err) } // 新增Ping验证 if err := db.Ping(); err != nil { panic(err) }
4. 处理截断表操作的错误并清理数据
完善truncateUsers函数的错误处理,并在测试结束后自动清理数据:
func truncateUsers(db *sql.DB) { _, err := db.Exec("TRUNCATE users") helper.PanicIfError(err) // 新增错误处理 } func TestCreateUsersSuccess(t *testing.T) { db := setupDB() defer truncateUsers(db) // 延迟调用,测试结束后清空表 router := setupRouter(db) // ... 后续代码 }
内容的提问来源于stack exchange,提问作者leo
相关产品推荐
相关产品推荐

