You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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逻辑。

修复步骤:

  1. 正确mock User的静态方法
    移除mockImplementation写法,直接初始化静态方法的mock:

    // 初始化静态方法mock
    User.findOne = jest.fn();
    User.updateOne = jest.fn();
    
  2. 设置合理的mock返回值
    在测试用例中直接给静态方法设置resolved值,updateOne建议返回符合数据库操作规范的结果对象:

    const fakeUser = { _id: "fakeUserId", defaultCard: "oldCardId" };
    User.findOne.mockResolvedValue(fakeUser);
    // 模拟mongoose updateOne的返回结果
    User.updateOne.mockResolvedValue({ acknowledged: true, modifiedCount: 1 });
    
  3. 移除多余代码
    删除无意义的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 18:07:40