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; });
额外调整点
- 测试文件里需要导入
sequelize实例,否则无法断言sequelize.define的调用情况:
const sequelize = require('../connection.js');
- 模型的
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
相关产品推荐
相关产品推荐

