beego.TestBeegoInit() 必须在 BeforeSuite 中调用,否则 beego.BeeApp.Handlers 为 nil 导致 panic;路径须与 go.mod module 完全一致,且需确保 routers.Init() 已执行、ORM 按需初始化。

beego.TestBeegoInit() 必须在 BeforeSuite 中调用
不初始化就跑测试,beego.BeeApp.Handlers 是 nil,所有请求都会 panic。关键不是“要不要初始化”,而是初始化时机和路径必须匹配实际项目结构。
常见错误现象:panic: runtime error: invalid memory address or nil pointer dereference,本质是路由没加载、配置没读取、ORM 没注册。
-
beego.TestBeegoInit("github.com/your/app")中的路径必须和go.mod里 module 声明完全一致;若用go mod init .本地初始化,传"."即可 - 确保
routers.Init()已执行——它负责把beego.Router()注册进全局路由表,否则/login这类路径根本不会被识别 - 如果模型层依赖数据库,需在
BeforeSuite中手动初始化 ORM(如orm.RunSyncdb("default", false, true)),否则models.User{}.查询会报no such table
用 beego.BeeApp.Handlers.ServeHTTP() 模拟真实 HTTP 流程
别用 http.DefaultClient 或起真实 server,那会绕过 Beego 的中间件、session、参数解析等核心链路,测了等于白测。
beego.BeeApp.Handlers 是一个标准 http.Handler,直接喂 *http.Request 和 httptest.ResponseRecorder 就能完整走通:路由匹配 → 控制器实例化 → Prepare() → 方法执行 → 模板渲染或 JSON 输出。
- GET 请求只需
http.NewRequest("GET", "/login", nil),注意路径带前导/ - POST 表单要设
Content-Type: application/x-www-form-urlencoded,并用url.Values{"username": {"admin"}}构造 body - POST JSON 必须设
Content-Type: application/json,且确认app.conf中EnableJsonUnmarshal = true,否则this.Ctx.Input.RequestBody为空
Ginkgo + Gomega 是控制器测试的事实标准
原生 testing 包写嵌套场景太啰嗦,比如“登录失败 → 提示错误 → 不跳转”,得手动拆成多个 func(t *testing.T)。Ginkgo 的 Describe/It 结构天然适配这种行为描述。
安装命令:go get github.com/onsi/ginkgo/v2/ginkgo 和 go get github.com/onsi/gomega,然后用 ginkgo -r 运行整个 tests/ 目录。
- 断言推荐用
Gomega:比如Expect(w.Code).To(Equal(http.StatusUnauthorized))比assert.Equal(t, http.StatusUnauthorized, w.Code)更易读 - 验证响应体内容时,优先检查
w.Body.String()是否含关键文本(如"<title>Login</title>"),而非完整 HTML 字符串,避免模板微调导致测试频繁失败 - 不要在
It块里做耗时操作(如连真实 MySQL),一律 mock 或用内存 SQLite,否则 CI 会变慢且不稳定
JSON 接口测试最容易漏掉 EnableJsonUnmarshal 配置
Beego 2.x 默认开启 EnableJsonUnmarshal,但很多团队从 1.x 升级后没改配置,结果 POST JSON 请求永远拿不到数据——this.ParseForm() 对 JSON 无效,this.Ctx.Input.RequestBody 又是空字节 slice。
查错方法:在控制器里加一行 beego.Debug("body len:", len(this.Ctx.Input.RequestBody)),测试时看日志是否输出 0。
- 必须在
conf/app.conf的[dev]或[test]区块显式写EnableJsonUnmarshal = true - 结构体字段要用指针标记可选字段(如
Name *string `json:"name"`),否则 JSON 中缺失该字段会导致解析失败 - 微信支付等第三方回调,body 是原始流,不能提前
json.Unmarshal,得先验签再解析,顺序错了签名就校验不过
app.conf 里一个空格,都可能让接口在浏览器里正常、在测试里 404 或 500。最保险的做法是:每次改完路由或控制器,立刻补一条 Ginkgo 测试,把请求路径、method、输入、预期状态码全锁死。


















