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

使用sequelize-auto生成模型后,Jest模拟findAll不生效如何解决?

Sequelize模型findAll方法Mock不生效解决方案

问题核心原因

你测试中模拟的models实例和控制器内部使用的models实例不是同一个对象:控制器每次引入init-models后都会调用initModels(sequelize)生成全新的models集合,你在测试文件中修改的是测试上下文单独初始化的models实例,自然不会影响控制器内部的逻辑。
另外你的测试写法还有两处问题:

  • 先手动给models.User.findAll赋值jest mock函数,又调用jest.spyOn属于重复操作,spyOn本身就会将目标方法包装为mock函数
  • findAll是异步方法,你直接返回普通对象而非Promise,即使mock生效也可能导致控制器中await相关逻辑异常

解决方案

方案1:将models封装为全局单例(推荐)

先统一models实例,避免重复初始化,后续所有业务代码和测试都共用同一个实例:

  1. 新建models/index.js作为单例导出文件:
const sequelize = require('../database/db');
const { initModels } = require("./init-models");
// 全局只初始化一次models
module.exports = initModels(sequelize);
  1. 修改控制器中的引入逻辑:
// 统一引入单例models,不要单独执行initModels
const models = require("../models/index");
const User = models.User;

const controllerMethod = async (req,res,next) => {
    // 原有逻辑不变
}
  1. 测试文件中直接对单例的findAll做模拟:
const models = require("../models/index");
// inside test case
// mock异步方法直接用mockResolvedValue返回Promise
const findAllSpy = jest.spyOn(models.User, "findAll").mockResolvedValue({});
await controllerMethod(req, res, next);
// 可添加断言验证调用
expect(findAllSpy).toHaveBeenCalled();

方案2:直接mock initModels方法

如果不想修改原有业务代码,可以直接mockinit-models模块,让所有调用initModels的地方都返回你预设的mock对象:
在测试文件顶部添加mock逻辑:

// 全局mock init-models模块
jest.mock('../models/init-models', () => ({
  initModels: jest.fn(() => ({
    User: {
      findAll: jest.fn().mockResolvedValue({})
    }
  }))
}));

之后无论控制器还是测试文件调用initModels,返回的User实例上的findAll都是你模拟的方法。

内容的提问来源于stack exchange,提问作者cmgchess

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 09:09:04