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

使用sequelize-mock测试时遇TypeError: User.findAll不是函数问题求助

使用sequelize-mock测试Sequelize模型时遇到User.findAll is not a function错误的解决方法

问题背景

我正在为基于PostgreSQL和Sequelize的简易REST API编写单元测试,相关代码及报错如下:

User模型代码

const sequelize = require('./../database/config')
const Sequelize = require('sequelize')
module.exports = sequelize.define(
  'User',
  {
    user_id: {
      type: Sequelize.UUID,
      primaryKey: true,
      defaultValue: Sequelize.UUIDV4,
      allowNull: false
    },
    login: {
      type: Sequelize.STRING,
      allowNull: false
    },
    password: {
      type: Sequelize.STRING,
      allowNull: false
    },
    age: {
      type: Sequelize.INTEGER,
      allowNull: false
    },
    is_deleted: {
      type: Sequelize.BOOLEAN,
      defaultValue: false,
      allowNull: false
    }
  },
  {
    timestamps: false,
    tableName: 'users'
  }
)

数据访问层代码

const User = require('../models/user')

exports.getUserById = (userId) => {
  return User.findOne({
    where: { user_id: userId, is_deleted: false }
  })
}

exports.getAllUsers = () => {
  return User.findAll({ where: { is_deleted: false } })
}

测试代码

let {
  getAllUsers,
} = require('./Users')

jest.mock('../models/user', () => () => {
  const SequelizeMock = require('sequelize-mock')
  const dbMock = new SequelizeMock()
  const UserMock = dbMock.define(
    'User',
    {
      user_id: '2',
      login: 'steve',
      password: 'good',
      age: 34,
      isDeleted: false
    }
  )
       
return UserMock
})

describe('User database', () => {
  it("getAllUsers should return users", async () => {
    const users = await getAllUsers()
    expect(users.length).toBeTruthy()
  })
})

报错信息

> nodejs-mentoring-2022@1.0.0 test
> jest --config ./jest.config.js --forceExit --coverage

 FAIL  data-access/User.test.js
  User database
    × getAllUsers should return users (2 ms)

  ● User database › getAllUsers should return users

    TypeError: User.findAll is not a function

       8 |
       9 | exports.getAllUsers = () => {
    > 10 |   return User.findAll({ where: { is_deleted: false } })
         |               ^
      11 | }
      12 |
      13 | exports.addOneUser = async (userData) => {

      at findAll (data-access/Users.js:10:15)
      at Object.getAllUsers (data-access/User.test.js:27:25)

----------|---------|----------|---------|---------|---------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s   
----------|---------|----------|---------|---------|---------------------
All files |      50 |      100 |   16.66 |      50 | 
 Users.js |      50 |      100 |   16.66 |      50 | 4,14-18,22,26-27,34
----------|---------|----------|---------|---------|---------------------
Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        0.973 s, estimated 1 s
Ran all test suites.
Force exiting Jest: Have you considered using `--detectOpenHandles` to detect async operations that kept running after all tests finished?

解决方法

问题核心是Jest mock的返回值不符合原始模型的导出结构:
原始模型直接导出sequelize.define()的结果(一个具备findAll等方法的模型对象),但当前mock返回的是一个函数,导致数据访问层引入的User是这个函数,而非模型对象,自然没有findAll方法。

修改后的测试代码:

let { getAllUsers } = require('./Users')

jest.mock('../models/user', () => {
  const SequelizeMock = require('sequelize-mock')
  const dbMock = new SequelizeMock()
  return dbMock.define('User', {
    user_id: '2',
    login: 'steve',
    password: 'good',
    age: 34,
    is_deleted: false // 注意字段名要和原始模型一致,原始是is_deleted而非isDeleted
  })
})

describe('User database', () => {
  it("getAllUsers should return users", async () => {
    // 手动设置mock返回值,让测试逻辑更可控
    require('../models/user').$queueResult([
      { user_id: '1', login: 'alice', password: 'test', age: 28, is_deleted: false },
      { user_id: '2', login: 'steve', password: 'good', age: 34, is_deleted: false }
    ])
    
    const users = await getAllUsers()
    expect(users.length).toBe(2)
    expect(users[0].login).toBe('alice')
  })
})

额外注意两个细节:

  1. mock的字段名必须和原始模型完全一致,原始模型用的是is_deleted,不要写成驼峰式的isDeleted,否则查询条件会匹配不到mock数据
  2. 使用$queueResult可以提前指定mock模型方法的返回值,让测试结果更可预期,避免依赖默认的mock数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 23:05:43