使用Jest测试Node.js函数时res.json未被调用的问题
Jest单元测试中res.json调用次数为0的问题排查
待测试函数
try { let user = await User.findOne({ _id: req.body.id }); if (user) { let userToUpdate = user; userToUpdate.defaultCard = req.body.idCard; try { await User.updateOne({ _id: req.body.id }, userToUpdate); console.log("b"); return res.json({ message: "Default succesfull" }); } catch (error) { return res.json({ message: "error" }); } } else { console.log("d"); res.json({ message: "error" }); } } catch (e) { console.log("e"); console.log(e); res.json({ message: "error" }); }
当前测试代码
let req = { headers: { authtoken: "fakeToken", }, body: { id: "fakeUserId", idCard: "fakeCardId", }, }; let res = { json: jest.fn(), }; const find_one_mock = jest.fn().mockResolvedValue(req.body.id); const update_one_mock = jest.fn().mockResolvedValue(req.body); User.mockImplementation(() => ({ findOne: find_one_mock, updateOne: update_one_mock, })); const fakeUser = { _id: "fakeUserId", defaultCard: "oldCardId" }; User.findOne.mockResolvedValue(fakeUser); User.updateOne.mockResolvedValue(fakeUser); await makeDefaultCard(req, res); await Promise.resolve(); expect(User.findOne).toHaveBeenCalledWith({ _id: "fakeUserId" }); expect(User.updateOne).toHaveBeenCalled(); expect(res.json).toHaveBeenCalledWith({ message: "Default succesfull", });
问题分析与修复方案
核心问题:User静态方法mock方式错误
原代码中User.findOne和User.updateOne是静态方法(直接通过Model类调用),但当前测试用mockImplementation模拟的是类实例的方法,导致实际调用时静态方法的mock未生效,函数执行可能进入异常分支或未走到res.json逻辑。
修复步骤:
正确mock User的静态方法
移除mockImplementation写法,直接初始化静态方法的mock:// 初始化静态方法mock User.findOne = jest.fn(); User.updateOne = jest.fn();设置合理的mock返回值
在测试用例中直接给静态方法设置resolved值,updateOne建议返回符合数据库操作规范的结果对象:const fakeUser = { _id: "fakeUserId", defaultCard: "oldCardId" }; User.findOne.mockResolvedValue(fakeUser); // 模拟mongoose updateOne的返回结果 User.updateOne.mockResolvedValue({ acknowledged: true, modifiedCount: 1 });移除多余代码
删除无意义的await Promise.resolve(),因为已经通过await makeDefaultCard(req, res)等待函数执行完成。
修复后的完整测试代码
let req = { headers: { authtoken: "fakeToken", }, body: { id: "fakeUserId", idCard: "fakeCardId", }, }; let res = { json: jest.fn(), }; // 初始化静态方法mock User.findOne = jest.fn(); User.updateOne = jest.fn(); const fakeUser = { _id: "fakeUserId", defaultCard: "oldCardId" }; User.findOne.mockResolvedValue(fakeUser); User.updateOne.mockResolvedValue({ acknowledged: true, modifiedCount: 1 }); await makeDefaultCard(req, res); expect(User.findOne).toHaveBeenCalledWith({ _id: "fakeUserId" }); expect(User.updateOne).toHaveBeenCalledWith( { _id: "fakeUserId" }, fakeUser ); expect(res.json).toHaveBeenCalledWith({ message: "Default succesfull", });
额外检查点
- 确认
makeDefaultCard是异步函数(内部包含await),测试中用await调用是正确的。 - 排查是否有其他中间件或前置逻辑拦截请求,导致
makeDefaultCard未完全执行。
内容的提问来源于stack exchange,提问作者ta7foun
相关产品推荐
相关产品推荐

