Node.js ESM环境下如何Stub默认导出的Auth中间件?
问题分析与解决方案
错误原因拆解
- 第一种方法报错:
sinon.stub(auth()).callsFake(...)逻辑错误。你先调用了auth()得到实际的中间件函数,再试图给这个临时函数打 stub,但这个函数和路由中使用的中间件引用无关,而且sinon.stub(函数)返回的存根函数不需要用callsFake——我们需要的是让auth()本身返回模拟中间件,而非修改已生成的中间件行为。 - 第二种方法报错:
import auth from '../../middlewares/auth.js'导入的auth就是默认导出的函数本身,不是包含default属性的模块对象,所以sinon.replace(auth, 'default')会提示属性不存在。 - 核心问题:你在
before中提前创建了app并加载了路由,此时路由已经调用auth()生成了实际中间件,后续在beforeEach中做的 stub 无法影响已初始化的中间件。
正确解决方案
调整测试生命周期,在创建应用和路由之前完成 stub,同时正确存根auth函数,让它返回直接执行next()的模拟中间件:
import express from 'express'; import supertest from 'supertest'; import { router } from "express-file-routing" import auth from '../../middlewares/auth.js'; import sinon from 'sinon' describe("/foo", () => { let app, request; // 将app创建移到beforeEach,确保每次测试都用最新的stub beforeEach(async () => { // 存根auth函数,让它返回跳过验证的中间件 const authStub = sinon.stub(auth).returns((req, res, next) => next()); // 重新创建app并加载路由(此时路由会使用stub后的auth) app = express(); app.use("/", await router()) request = supertest(app); // 测试结束后恢复原函数 return () => authStub.restore(); }); // 示例测试用例 it("should bypass auth middleware successfully", async () => { const res = await request.get("/foo"); // 你的断言逻辑,比如验证响应状态码等 expect(res.status).toBe(200); }); });
如果遇到 ES 模块只读属性无法直接 stub 的问题,可以改用sinon.replace替换整个auth函数:
beforeEach(async () => { // 定义模拟的auth生成函数 const mockAuth = () => (req, res, next) => next(); // 替换原auth函数 sinon.replace(auth, mockAuth); app = express(); app.use("/", await router()) request = supertest(app); return () => sinon.restore(); });
内容的提问来源于stack exchange,提问作者bcsta
相关产品推荐
相关产品推荐

