如何在Jest单测中取消express-jwt的ESM模块Mock?
解决方案
问题出在模块加载时机:你的Express app在测试文件导入阶段就已经初始化,并且使用了setupAfterEnv.js中全局mock的express-jwt。后续修改mock的操作不会影响已经创建好的app实例,因为中间件已经挂载完成。
要在单个测试中使用真实的express-jwt,需要按以下步骤操作:
- 重置模块缓存:清除已加载的模块,确保后续导入的模块使用最新的mock配置。
- 重新定义mock为真实实现:覆盖全局的mock,让
express-jwt返回真实模块。 - 动态导入app:此时app会使用真实的
express-jwt重新初始化。
具体代码示例:
// myMiddleware.test.js test("验证无效token触发错误处理中间件", async () => { // 重置所有已加载的模块缓存 jest.resetModules(); // 重新mock express-jwt为真实实现 jest.unstable_mockModule("express-jwt", () => jest.requireActual("express-jwt")); // 动态导入app和supertest(避免提前加载导致的mock复用) const { app } = await import("../path/to/your/app-file"); // 替换为你的app文件实际路径 const request = (await import("supertest")).default; // 发送不带token的请求 const response = await request(app).get("/"); // 根据你的错误处理逻辑调整断言 expect(response.statusCode).toBe(401); expect(response.body).toHaveProperty("error", "Invalid token"); });
为什么之前的方法无效?
jest.restoreAllMocks():仅恢复mock的实现,但app实例已经在初始化时使用了旧的mock中间件,无法更新已挂载的中间件。spyOn:针对的是已导入模块的实例,而app已经使用了mock版本创建的中间件,修改spy不会改变已存在的中间件逻辑。- 直接在测试中调用
jest.unstable_mockModule:模块缓存未清除,app仍然使用之前加载的mock版本。
内容的提问来源于stack exchange,提问作者Renaud Aubert
相关产品推荐
相关产品推荐

