使用Jest和Supertest模拟Express带参数柯里化中间件失败原因
柯里化Express中间件Jest模拟失败的原因及解决
核心原因:模拟时机晚于路由初始化
Express加载路由文件时,advancedAuthGuard(false)会立即执行,返回的内层函数才是注册给路由的中间件。如果你的测试代码是先导入路由/应用,再去模拟advancedAuthGuard,此时路由已经把未正确模拟的undefined当成中间件注册了,直接触发Express的类型校验错误。
而单独模拟时,你是直接调用advancedAuthGuard(false),此时模拟已经生效,所以能返回预期的函数——这就是场景差异导致的问题。
解决方法
必须在路由模块加载前完成模拟,保证路由初始化时用的是模拟后的函数:
方案1:提前拦截模块(全局模拟)
在测试文件最开头就用jest.mock模拟中间件模块,确保路由加载时拿到的是模拟函数:
// 测试文件第一行就写模拟逻辑 jest.mock('./middleware/advancedAuthGuard', () => { // 复刻柯里化结构:外层接收参数,返回内层中间件函数 return jest.fn(() => (req, res, next) => next()); }); // 之后再导入路由、应用等模块 const request = require('supertest'); const app = require('./app');
方案2:用重置模块实现用例隔离
如果不同测试用例需要不同的模拟逻辑,可以在每个用例前重置模块并重新模拟:
let app; beforeEach(() => { // 重置已加载的模块缓存 jest.resetModules(); // 重新模拟中间件 jest.mock('./middleware/advancedAuthGuard', () => { return jest.fn((condition) => (req, res, next) => { // 可根据condition参数定制模拟逻辑 next(); }); }); // 重新导入应用(确保用的是最新模拟) app = require('./app'); });
关键验证点
- 模拟函数必须和原中间件的柯里化结构一致:外层函数接收
additionalCondition参数,返回一个(req, res, next)格式的函数。 - 严格控制模块导入顺序:先模拟,再导入路由/应用,否则模拟不会生效。
内容的提问来源于stack exchange,提问作者Ecora
相关产品推荐
相关产品推荐

