Jest中express-session跨接口调用无法持久化会话信息的解决方法
问题
我用express-session最简方式存储登录信息:
req.session.userId = user.id
开发环境下配置完全正常,配置详情如下:
app.use(express.json()) app.use(sessions({ secret: "secretthatwillbeputinenv", saveUninitialized: true, cookie: { maxAge: 1000 * 60 * 60 * 24 }, resave: false })); app.use(cookieParser()); app.use(express.urlencoded({ extended: true })); app.use(cors()) app.use("/", router);
但用supertest调用sign_in接口后,再调用另一个读取会话持久化信息的接口时,发现信息未保留:req.session能返回会话对象,但userId为null。如何在Jest中无hack、无模拟地让express-session正常工作?
解决方法
复用supertest代理实例
每次发起请求必须用同一个request(app)创建的代理对象,不能每次都重新生成。新的代理实例会开启全新会话上下文,之前的session数据不会被继承。示例代码:// 在测试用例外部创建共享代理 const agent = request(app); test('登录后读取会话信息', async () => { // 第一步:调用登录接口 await agent.post('/sign_in') .send({ username: 'test', password: '123456' }) .expect(200); // 第二步:复用同一个agent调用会话接口 const res = await agent.get('/get_user_info') .expect(200); expect(res.body.userId).not.toBeNull(); });修正中间件加载顺序
当前配置中cookieParser()在sessions()之后,这会导致session无法正确解析cookie。正确顺序是先加载cookieParser,再初始化session:// 调整后的中间件顺序 app.use(express.json()) app.use(cookieParser()); // 移到session中间件之前 app.use(sessions({ secret: "secretthatwillbeputinenv", saveUninitialized: true, cookie: { maxAge: 1000 * 60 * 60 * 24 }, resave: false })); app.use(express.urlencoded({ extended: true })); app.use(cors()) app.use("/", router);配置CORS允许凭证传递
如果涉及跨域场景,CORS需要开启credentials: true,测试请求也需带上凭证标识(supertest中用withCredentials()):// 修正CORS配置 app.use(cors({ credentials: true, origin: true // 或指定具体前端域名 })); // 测试请求携带凭证 await agent.post('/sign_in') .withCredentials() .send({ username: 'test', password: '123456' });按需关闭Jest测试隔离
Jest默认每个测试用例完全隔离,若需跨用例共享会话,可在测试文件开头添加jest.isolateModules(false),但更推荐在单个用例内完成登录+验证流程,保持用例独立性。
内容的提问来源于stack exchange,提问作者Leo
相关产品推荐
相关产品推荐

