Mock中间件是测试时临时替换真实中间件行为的函数,用于隔离依赖、控制上下文或跳过非核心逻辑;Fiber无原生支持,需通过变量替换、gock拦截或完整链模拟实现,且必须在app.Test()前完成替换。

Mock中间件不是 Fiber 原生概念,得自己造
Fiber 没有内置 “Mock 中间件” 类型或注册机制——它只认 func(*fiber.Ctx) error。所谓 Mock 中间件,本质是**在测试时临时替换真实中间件行为的函数**,用于隔离依赖、控制上下文状态或跳过鉴权/日志等非核心逻辑。
常见错误是试图在测试里调用 app.Use() 动态覆盖已注册中间件,这不行:Fiber 的中间件链在启动时就固化了,app.Use() 只能追加,不能替换或删除。
- 真实中间件(如 JWT 验证)必须被绕过或重写,不能靠“禁用开关”参数控制
- Mock 中间件必须在测试前、
app.Test()调用前完成替换,否则无效 - 别在 handler 里用
c.Locals手动塞 mock 数据——那是补丁,不是可复用的中间件
用函数变量替换中间件实现最直接
把要 Mock 的中间件定义成包级变量,测试时直接赋值新函数:
// auth.go
var AuthMiddleware = func(c *fiber.Ctx) error {
token := c.Get("Authorization")
if token == "" {
return c.Status(401).SendString("unauthorized")
}
return c.Next()
}
// main.go
app.Use(AuthMiddleware)
测试中替换:
// auth_test.go
func TestWithMockAuth(t *testing.T) {
// 保存原值,测试后恢复(避免影响其他 test)
original := AuthMiddleware
defer func() { AuthMiddleware = original }()
AuthMiddleware = func(c *fiber.Ctx) error {
c.Locals("user_id", 123)
return c.Next()
}
app := fiber.New()
setupRoutes(app) // 此时用的是新 AuthMiddleware
req, _ := http.NewRequest("GET", "/api/profile", nil)
resp, _ := app.Test(req)
// 断言返回 200,而非 401
}
- 适用于单个中间件、无跨包引用的场景
- 必须确保业务代码引用的是该变量,而不是内联匿名函数
- 若中间件在第三方包里(如
fiber/jwt),此法失效,得换方案
用 httptest.NewServer + gock 拦截外部依赖更可靠
当你的 Fiber 服务调用了外部 API(比如用户中心、支付网关),而你想在测试中 Mock 它们的响应,httptest.NewServer 不适用——它只 mock 本服务的 HTTP 入口,不处理 outbound 请求。
此时用 gock 拦截 http.DefaultClient 或自定义 client 发出的请求:
func TestExternalAPIFailure(t *testing.T) {
defer gock.Off() // 必须清理,否则污染后续测试
gock.New("https://api.example.com").
Get("/users/123").
Reply(503).
JSON(map[string]string{"error": "service unavailable"})
app := fiber.New()
setupRoutes(app)
req, _ := http.NewRequest("GET", "/profile/123", nil)
resp, _ := app.Test(req)
assert.Equal(t, 503, resp.StatusCode)
}
-
gock必须在测试开始时启用,在defer gock.Off()清理 - 如果业务用了自定义
*http.Client,需显式调用gock.Intercept(client.Transport) - 别漏掉
gock.Flush()—— 否则未匹配的请求会静默失败,难定位问题
真正难的是中间件顺序与嵌套逻辑的 Mock
Fiber 中间件执行是嵌套的:A → B → handler → B(返回) → A(返回)。如果你 Mock 的是中间件 B,但它的行为依赖中间件 A 设置的 c.Locals,而你又没 Mock A,那测试就会崩。
这时候不能只换一个中间件,得构造完整链:
- 要么把 A 和 B 都替换成可控版本(推荐,显式可靠)
- 要么改用
app.Test()+httptest.NewRecorder直接测 handler,绕过中间件链(适合单元级逻辑验证) - 绝对不要在测试里用
time.Sleep等待中间件“生效”——Fiber 是同步执行的,没有异步延迟
最易忽略的一点:Mock 中间件里调用 c.Next() 后,必须确保 handler 真的被执行了。如果 Mock 函数提前 return nil 或 panic,handler 就不会运行,测试断言会错判。


















