英文:
Express Jest problem running test with Sequelize
问题
问题
在尝试在我的Express应用程序上运行一些Jest测试时,我遇到了这个错误:
> FAIL  models/tests/user.model.test.js
● 测试套件运行失败
TypeError: Sequelize is not a constructor
  2 | const path = require('path');
  3 |
> 4 | const sequelize = new Sequelize({
    |                   ^
  5 |     dialect: 'sqlite',
  6 |     storage: path.join(__dirname, 'database.sqlite'),
  7 |     logging: console.log // 输出日志到控制台
  在 Object.<anonymous> (models/connection.js:4:19)     
  在 Object.require (models/user.model.js:2:19)
  在 Object.require (models/__tests__/user.model.test.js:3:64)
代码
这是我的Sequelize连接的实际代码:
const Sequelize = require('sequelize'); // 也尝试了 const { Sequelize }
const path = require('path');
const sequelize = new Sequelize({
    dialect: 'sqlite',
    storage: path.join(__dirname, 'database.sqlite'),
    logging: console.log // 输出日志到控制台
});
sequelize.authenticate()
    .then(() => {
        console.log('数据库连接成功建立');
    })
    .catch((error) => {
        console.error('连接到数据库时出错:', error);
    });
module.exports = sequelize;
然后这是我在user.model.js上运行的实际测试的代码:
const { DataTypes } = require('sequelize');
const bcrypt = require('bcrypt');
const { User, createUser, findUserById, findUserByUsername } = 
require('../user.model.js');
jest.mock('sequelize', () => ({
    define: jest.fn(),
    sync: jest.fn(),
    findOne: jest.fn(),
    create: jest.fn(),
    query: jest.fn(),
}));
jest.mock('bcrypt', () => ({
    hash: jest.fn(),
}));
describe('User Model', () => {
    beforeEach(() => {
        jest.clearAllMocks();
    });
test('应定义用户模型', () => {
    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('应创建用户并散列密码', async () => {
    bcrypt.hash.mockResolvedValue('hashedPassword');
    const username = 'testuser'
    const password = 'testpassword';
    const expectedUser = {
        id: 1,
        username,
        password: 'hashedPassword',
    };
    User.create.mockResolvedValue(expectedUser);
    const user = await createUser(username, password);
    expect(User.create).toHaveBeenCalledTimes(1);
    expect(User.create).toHaveBeenCalledWith({
        username,
        password: 'hashedPassword',
    });
    expect(user).toEqual(expectedUser);
    expect(bcrypt.hash).toHaveBeenCalledWith(password, 10);
});
});
在我正在运行测试的user.model.js文件中,我使用 const sequelize = require('./connection.js'); 导入连接模块。只有在我尝试运行测试时才会遇到问题,如果我启动服务器,它将正常启动,我可以与数据库交互。
我尝试过的
我问过ChatGPT,它说要确保我有正确的依赖项,并确保我在连接模块中正确导入sequelize。我尝试了多种不同的导入sequelize的方式,但仍然出现相同的问题。我知道正确的依赖项已安装,因为我的其他测试工作正常。
英文:
Problem
While trying to run some Jest testing on my Express application, I encounter this error:
> FAIL  models/tests/user.model.test.js
● Test suite failed to run
TypeError: Sequelize is not a constructor
  2 | const path = require('path');
  3 |
> 4 | const sequelize = new Sequelize({
    |                   ^
  5 |     dialect: 'sqlite',
  6 |     storage: path.join(__dirname, 'database.sqlite'),
  7 |     logging: console.log // Output logs to the console
  at Object.<anonymous> (models/connection.js:4:19)     
  at Object.require (models/user.model.js:2:19)
  at Object.require (models/__tests__/user.model.test.js:3:64)
Code
This is the actual code for my Sequelize connection:
const Sequelize = require('sequelize'); // also tried const { Sequelize }
const path = require('path');
const sequelize = new Sequelize({
    dialect: 'sqlite',
    storage: path.join(__dirname, 'database.sqlite'),
    logging: console.log // Output logs to the console
});
sequelize.authenticate()
    .then(() => {
        console.log('Database connection established successfully');
    })
    .catch((error) => {
        console.error('Error connecting to the database: ', error);
    });
module.exports = sequelize;
Then this is the code for my actual tests im running on user.model.js:
const { DataTypes } = require('sequelize');
const bcrypt = require('bcrypt');
const { User, createUser, findUserById, findUserByUsername } = 
require('../user.model.js');
jest.mock('sequelize', () => ({
    define: jest.fn(),
    sync: jest.fn(),
    findOne: jest.fn(),
    create: jest.fn(),
    query: jest.fn(),
}));
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',
    };
    User.create.mockResolvedValue(expectedUser);
    const user = await createUser(username, password);
    expect(User.create).toHaveBeenCalledTimes(1);
    expect(User.create).toHaveBeenCalledWith({
        username,
        password: 'hashedPassword',
    });
    expect(user).toEqual(expectedUser);
    expect(bcrypt.hash).toHaveBeenCalledWith(password, 10);
});
});
Inside my user.model.js file that im running tests on, I import the connection module with const sequelize = require('./connection.js');. I only run into the problem when I try and run my test, if I start the server it will start no problem and I can interact with the database.
What I've Tried
I've asked chatGPT it said to make sure that I have the right dependencies, and to make sure I import sequelize properly in the connection module. I've tried multiple different ways of importing sequelize, but same issue. I know the right dependencies are installed because my other tests work.
答案1
得分: 1
Sequelize 是由 sequelize 模块导出的一个类。所以你需要像这样模拟这个类:jest.fn(() => instance)。
在模拟之后,Sequelize 类将变成 jest.fn(() => instance),
new Sequelize(/**/) 将返回 instance。
你应该使用 Mocking Partials,这意味着我们只想模拟 Sequelize 类,并继续使用其他东西的原始实现。
import Sequelize, { DataTypes } from 'sequelize';
jest.mock('sequelize', () => {
  return {
    ...jest.requireActual('sequelize'),
    default: jest.fn(() => ({
      define: jest.fn(),
      sync: jest.fn(),
      findOne: jest.fn(),
      create: jest.fn(),
      query: jest.fn(),
    })),
    __esModule: true,
  };
});
describe('76657256', () => {
  test('should pass', () => {
    expect(jest.isMockFunction(Sequelize)).toBeTruthy();
    expect(DataTypes.INTEGER).toBeDefined();
  });
});
英文:
Sequelize is a class exported by sequelize module. So you need to mock the class like this: jest.fn(() => instance).
After mocking, the Sequelize class will become jest.fn(() => instance),
new Sequelize(/**/) will return the instance.
You should use Mocking Partials, which means we just want to mock the Sequelize class and keep using the original implementation of other things.
import Sequelize, { DataTypes } from 'sequelize';
jest.mock('sequelize', () => {
  return {
    ...jest.requireActual('sequelize'),
    default: jest.fn(() => ({
      define: jest.fn(),
      sync: jest.fn(),
      findOne: jest.fn(),
      create: jest.fn(),
      query: jest.fn(),
    })),
    __esModule: true,
  };
});
describe('76657256', () => {
  test('should pass', () => {
    expect(jest.isMockFunction(Sequelize)).toBeTruthy();
    expect(DataTypes.INTEGER).toBeDefined();
  });
});
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论