Jest测试报错req.session.save is not a function如何mock该方法
问题原因
使用httpMocks.createRequest()生成的模拟请求对象,默认不会自动注入express-session中间件挂载的session属性,自然也不存在异步方法save(),因此执行到await req.session.save()时会抛出req.session.save is not a function错误。
另外原测试代码还有两个隐性问题:
describe拼写错误,写成了descibe- 调用async类型的controller方法时没有加
await等待异步逻辑执行完成,断言会在业务逻辑跑完前触发,大概率得到不符合预期的结果。
修复方案
在初始化模拟请求对象后,手动挂载mock的session对象,将save方法实现为返回Promise的jest mock函数即可,同时修正异步调用和拼写问题。
修正后的测试代码如下:
describe('test',()=> { let req: any; let res: any; beforeEach(() => { // 每个用例执行前重新生成mock对象,避免用例间状态污染 req = httpMocks.createRequest(); res = httpMocks.createResponse(); // 挂载mock的session实现 req.session = { save: jest.fn().mockResolvedValue(undefined) }; }); it('should connected', async () => { // 等待异步controller执行完成 await myController.connect(req, res); expect(res.statusCode).toBe(200); // 可选:断言session.save被正确调用 expect(req.session.save).toHaveBeenCalledTimes(1); // 可选:断言session内写入的token符合预期 expect(req.session.testToken).toEqual({ refresh_token: expect.any(String), access_token: expect.any(String), expires_in: 1200 }); expect(res._isEndCalled()).toBeTruthy(); expect(res._getJSONData()).toEqual({success:true, message:'Connected'}); }); })
注意事项
req.session.save是异步方法,mock时必须返回Promise,推荐直接用jest.fn().mockResolvedValue(undefined)模拟成功场景,如果要测试save失败的分支,可以在用例内单独用mockRejectedValue模拟抛出错误的情况。- 涉及异步逻辑的测试用例必须加
async/await等待逻辑执行完毕,否则断言时机不对会出现偶现失败的问题。 - 把mock初始化逻辑放到
beforeEach中,可以保证每个用例拿到的都是全新的mock对象,避免上一个用例修改session内容、记录save调用次数导致下一个用例断言失败。
内容的提问来源于stack exchange,提问作者Shivam Sharma
相关产品推荐
相关产品推荐

