You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Golang httptest POST请求:加JSON头遇运行时错误,不加无法读取负载

登录路由测试问题排查

问题描述

我在给一个仅需2个必填参数的简易登录路由写测试,添加application/json请求头发起POST请求时会返回运行时错误;移除该请求头后错误消失,但又无法读取请求负载。

测试代码

package main

import (
    "fmt"
    "net/http"
    "net/http/httptest"
    "strings"
    "testing"

    "github.com/gigilaw/ultihats/routes"
    "github.com/stretchr/testify/assert"
)

func TestRegisterEmailRoute(t *testing.T) {
    router := routes.ApiRoutes()

    payload := strings.NewReader(`{
        "email":"abc@gmail.com",
        "password": "abc12345"
        }`,
    )

    w := httptest.NewRecorder()
    req, err := http.NewRequest("POST", "/login", payload)

    if err != nil {
        fmt.Println(err)
    }
    req.Header.Add("Content-Type", "application/json")
    router.ServeHTTP(w, req)
    assert.Equal(t, 200, w.Code)
}

报错信息

2022/11/02 18:32:35 [Recovery] 2022/11/02 - 18:32:35 panic recovered:
POST /login HTTP/1.1
Content-Type: application/json


runtime error: invalid memory address or nil pointer dereference
/usr/local/go/src/runtime/panic.go:260 (0x104f8d5)
        panicmem: panic(memoryError)
/usr/local/go/src/runtime/signal_unix.go:835 (0x104f8a5)
        sigpanic: panicmem()
/Users/gigilaw/Desktop/go/pkg/mod/gorm.io/gorm@v1.24.0/gorm.go:372 (0x1698f18)
        (*DB).getInstance: if db.clone > 0 {
/Users/gigilaw/Desktop/go/pkg/mod/gorm.io/gorm@v1.24.0/chainable_api.go:279 (0x1691995)
        (*DB).Preload: tx = db.getInstance()
/Users/gigilaw/Desktop/go/src/github.com/gigilaw/ultihats/api/controllers/authController.go:64 (0x16d894e)
        UserLogin: initializers.DB.Preload("DiscSkills").First(&user, "email = ?", login.Email)
/Users/gigilaw/Desktop/go/pkg/mod/github.com/gin-gonic/gin@v1.8.1/context.go:173 (0x1538181)
        (*Context).Next: c.handlers[c.index](c)
/Users/gigilaw/Desktop/go/pkg/mod/github.com/gin-gonic/gin@v1.8.1/recovery.go:101 (0x153816c)
        CustomRecoveryWithWriter.func1: c.Next()
/Users/gigilaw/Desktop/go/pkg/mod/github.com/gin-gonic/gin@v1.8.1/context.go:173 (0x1537286)
        (*Context).Next: c.handlers[c.index](c)
/Users/gigilaw/Desktop/go/pkg/mod/github.com/gin-gonic/gin@v1.8.1/logger.go:240 (0x1537269)
        LoggerWithConfig.func1: c.Next()
/Users/gigilaw/Desktop/go/pkg/mod/github.com/gin-gonic/gin@v1.8.1/context.go:173 (0x1536350)
        (*Context).Next: c.handlers[c.index](c)
/Users/gigilaw/Desktop/go/pkg/mod/github.com/gin-gonic/gin@v1.8.1/gin.go:616 (0x1535fb8)
        (*Engine).handleHTTPRequest: c.Next()
/Users/gigilaw/Desktop/go/pkg/mod/github.com/gin-gonic/gin@v1.8.1/gin.go:572 (0x1535afc)
        (*Engine).ServeHTTP: engine.handleHTTPRequest(c)
/Users/gigilaw/Desktop/go/src/github.com/gigilaw/ultihats/api/tests/userTest_test.go:31 (0x171d946)
        TestRegisterEmailRoute: router.ServeHTTP(w, req)
/usr/local/go/src/testing/testing.go:1446 (0x111d70a)
        tRunner: fn(t)
/usr/local/go/src/runtime/asm_amd64.s:1594 (0x106db80)
        goexit: BYTE    $0x90   // NOP

问题原因与解决办法

从报错栈能直接定位问题:panic出现在authController.go的initializers.DB.Preload("DiscSkills").First(...)行,说明**initializers.DB是nil指针**——你的测试代码没有初始化数据库连接实例。

  • 解决核心问题:在测试函数创建路由之前,先调用数据库初始化逻辑,和业务服务启动时的流程一致。比如添加initializers.InitDB()(根据你的项目实际初始化函数调整),确保initializers.DB被正确赋值为GORM的DB实例。
  • 可选优化:如果不想依赖真实数据库,可以用内存数据库(如SQLite的内存模式)或者Mock库模拟GORM的DB实例,让测试更轻量化,不依赖外部服务。
  • 关于有无请求头的差异:去掉Content-Type: application/json后,Gin不会自动解析JSON请求体,登录逻辑可能因为没获取到参数提前返回,没走到数据库查询的代码分支,所以没触发nil指针panic,但这只是规避了错误,不是解决方法。

内容的提问来源于stack exchange,提问作者Gigi Law

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 05:50:37