Fiber 的 app.Test() 方法不启动服务器,直接将 *http.Request 喂给路由引擎,完整执行中间件链、路由匹配和 handler;需用 http.NewRequest 构造含完整上下文的请求,并断言中间件副作用(如 Locals、Header、状态码)及边界路径/方法覆盖。

用 app.Test() 模拟请求走完整中间件链
Fiber 的 Test() 方法是专为测试设计的,它不启动 HTTP 服务器,而是把 *http.Request 直接喂给路由引擎,中间件、路由匹配、handler 全部真实执行。这是验证自定义中间件逻辑是否生效的最可靠方式。
常见错误现象:写完中间件后只跑 handler 单元测试,结果中间件根本没被调用;或者用 curl 测,但漏掉了 header、method、path 等关键上下文,导致中间件条件判断失败。
- 必须用
http.NewRequest()构造带完整上下文的请求,比如POST /api/data+Content-Type: application/json+ body - 中间件里调用
c.Next()后,c.Response().StatusCode才会反映最终状态码,别在中间件里提前读c.Status() - 若中间件修改了
c.Locals或c.Context().Value(),需在 handler 里显式取值并断言,Test()不会自动暴露这些内部状态
中间件返回 error 时要检查 resp.StatusCode 和响应体
自定义中间件若返回非 nil error(比如鉴权失败调 c.Status(401).SendString("unauthorized")),Fiber 默认会终止链并返回该响应——但前提是中间件函数签名正确:func(*fiber.Ctx) error。签名错或 panic 会导致 Test() 报 panic: runtime error 而不是 401。
容易踩的坑:中间件里写了 c.SendStatus(401) 却忘了 return,后续 handler 仍会执行,最终状态码被覆盖为 200。
- 测试时 assert
resp.StatusCode == 401,再读io.ReadAll(resp.Body)验证响应内容是否为 "unauthorized" - 若中间件依赖外部服务(如 Redis 校验 token),测试中应先用
gomock或接口替换,避免真实调用拖慢或失败 - 注意
Test()默认超时 1 秒,中间件含阻塞操作(如未 mock 的time.Sleep)会直接 timeout
测试中间件对不同路径/方法的路由控制效果
很多中间件按前缀生效(如 app.Use("/admin", auth)),或只针对特定 method(如只拦截 POST)。光测 /admin 成功不够,必须覆盖边界情况。
典型遗漏场景:中间件挂载在 /api,但测试只打 /api/users,漏了 /api/(末尾斜杠)、/api/v1/health(嵌套更深)、/apixxx(前缀不匹配)。
- 构造多个
http.Request:路径分别设为/api、/api/、/api/users、/apix、/health,观察中间件是否仅在预期路径触发 - 换 method 测试:中间件若用了
app.Post("/login", middleware, handler),必须用http.MethodPost请求,GET应完全绕过 - 若中间件内有
c.Path()或c.Route().Path判断,注意 Fiber 默认会 normalize path(如//foo→/foo),测试时路径要跟实际一致
验证中间件修改 context 的副作用是否符合预期
中间件常往 c.Locals 写入数据供后续 handler 使用(如解析 JWT 后存 user_id),或修改 c.Request().Header(如加 trace id)。这些副作用不会自动透出到测试断言中,必须主动提取。
最容易忽略的是:handler 里用 c.Locals("user_id") 取值,但测试时只检查了 status code,没验证这个值是否存在或是否正确。
- 在 handler 里把
c.Locals值写进响应体(如c.JSON(200, map[string]interface{}{"user_id": c.Locals("user_id")})),再断言 JSON 字段 - 若中间件设置了
c.Set("X-Trace-ID", "abc"),需在 handler 里调c.Get("X-Trace-ID")并写入响应,否则Test()返回的resp.Header不包含它(Set是响应头,但中间件阶段还没到写响应) - 避免在中间件里直接操作
c.Context().Done()或c.Context().Deadline(),Test()的 context 是干净的,无 cancel 信号,测不出超时逻辑











