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

Express中使用Jest测试Sequelize时出现构造函数错误

解决Jest测试中Sequelize不是构造函数的错误

问题根源

你在Jest测试里用jest.mock('sequelize')模拟的对象只包含define、sync等方法,但没有模拟Sequelize构造函数本身。当connection.js执行new Sequelize()时,找不到合法的构造函数,就会抛出TypeError: Sequelize is not a constructor错误。

修复方案

修改Sequelize的模拟逻辑,让它返回一个可被new调用的构造函数,同时构造函数要返回包含所需方法的实例对象,还要模拟业务代码用到的DataTypes:

jest.mock('sequelize', () => {
  // 模拟Sequelize实例的核心方法
  const mockSequelizeInstance = {
    define: jest.fn(),
    authenticate: jest.fn().mockResolvedValue(true),
    sync: jest.fn(),
  };

  // 模拟Sequelize构造函数,调用后返回上面的实例
  const mockSequelize = jest.fn(() => mockSequelizeInstance);

  // 模拟DataTypes,匹配业务代码里的使用
  mockSequelize.DataTypes = {
    INTEGER: 'INTEGER',
    STRING: 'STRING',
  };

  return mockSequelize;
});

额外调整点

  1. 测试文件里需要导入sequelize实例,否则无法断言sequelize.define的调用情况:
const sequelize = require('../connection.js');
  1. 模型的create方法是sequelize.define返回的模型对象的方法,所以要让define的mock返回带有create方法的对象,确保createUser逻辑能正常触发mock:
// 在创建用户的测试用例里添加
sequelize.define.mockReturnValue({
  create: jest.fn().mockResolvedValue(expectedUser),
});

完整修复后的测试文件示例

const { DataTypes } = require('sequelize');
const bcrypt = require('bcrypt');
const { User, createUser, findUserById, findUserByUsername } = require('../user.model.js');
const sequelize = require('../connection.js'); // 新增导入

jest.mock('sequelize', () => {
  const mockSequelizeInstance = {
    define: jest.fn(),
    authenticate: jest.fn().mockResolvedValue(true),
    sync: jest.fn(),
  };

  const mockSequelize = jest.fn(() => mockSequelizeInstance);
  mockSequelize.DataTypes = {
    INTEGER: 'INTEGER',
    STRING: 'STRING',
  };

  return mockSequelize;
});

jest.mock('bcrypt', () => ({
  hash: jest.fn(),
}));

describe('User Model', () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  test('Should define User model', () => {
    expect(sequelize.define).toHaveBeenCalledTimes(1);
    expect(sequelize.define).toHaveBeenCalledWith('users', {
      id: {
        type: DataTypes.INTEGER,
        primaryKey: true,
        autoIncrement: true,
      },
      username: {
        type: DataTypes.STRING,
        allowNull: false,
        unique: true,
      },
      password: {
        type: DataTypes.STRING,
        allowNull: false,
      },
    });
  });

  test('Should create user and hash password', async () => {
    bcrypt.hash.mockResolvedValue('hashedPassword');

    const username = 'testuser';
    const password = 'testpassword';

    const expectedUser = {
      id: 1,
      username,
      password: 'hashedPassword',
    };

    // 让define返回带有create方法的模型对象
    sequelize.define.mockReturnValue({
      create: jest.fn().mockResolvedValue(expectedUser),
    });

    const user = await createUser(username, password);

    expect(bcrypt.hash).toHaveBeenCalledWith(password, 10);
    expect(sequelize.define().create).toHaveBeenCalledTimes(1);
    expect(sequelize.define().create).toHaveBeenCalledWith({
      username,
      password: 'hashedPassword',
    });

    expect(user).toEqual(expectedUser);
  });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 05:12:46