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

如何在Jest中为跨文件的测试组统一初始化数据库?

问题原因

Jest运行测试分为两个固定阶段:

  1. 测试收集阶段:同步执行所有顶层/嵌套的describe回调、测试分组注册逻辑,提前把所有it/test用例收集到调度队列中。这个阶段beforeAll钩子还未触发,你此时传入分组函数的sequelize还是初始的null值。
  2. 测试执行阶段:所有用例收集完成后,才会按顺序执行beforeAll、测试用例、afterAll钩子,此时sequelize才会被正确赋值。
解决方案

方案1:测试执行阶段再读取实例

不要在测试注册阶段就把sequelize传入分组函数,让分组内的测试用例在执行时再读取外层作用域的sequelize变量即可:

// 改造前的分组函数(注册阶段就依赖sequelize,不可行)
// function testGroupOne(sequelize) {
//   return () => {
//     it('测试用户模型存在', () => {
//       expect(sequelize.models.User).toBeDefined()
//     })
//   }
// }

// 改造后的分组函数,执行阶段再读变量
function testGroupOne() {
  return () => {
    it('测试用户模型存在', () => {
      // 测试执行时beforeAll已经跑完,sequelize已经完成赋值
      expect(sequelize.models.User).toBeDefined()
    })
  }
}

// 入口测试文件调整后代码
let sequelize = null

beforeAll(async () => {
  sequelize = await initDataBase(config)
})

afterAll(async () => {
  await sequelize.drop()
})

describe('DB testing', () => {
  it('Test #0', () => expect(true).toEqual(true))
  // 不需要提前传sequelize参数
  testGroupZero()()
  describe('Test Group #1', testGroupOne())
  describe('Test Group #2', testGroupTwo())
})

方案2:跨文件共享实例用global挂载

如果你的测试分组分散在不同文件,无法共享外层作用域变量,可以把初始化后的sequelize挂载到Jest的全局对象上:

// 入口测试/公共setup文件
beforeAll(async () => {
  global.sequelize = await initDataBase(config)
})

afterAll(async () => {
  await global.sequelize.drop()
})

各个测试分组的文件内直接读取global.sequelize即可,执行时就能拿到初始化完成的实例。

方案3:全局统一初始化用setupFilesAfterEnv配置

如果要给所有测试文件统一加初始化逻辑,不需要每个文件重复写beforeAll/afterAll,可以修改Jest配置:

  1. 在jest.config.js中添加配置项:
module.exports = {
  // 其余配置保持不变
  setupFilesAfterEnv: ['<rootDir>/test/global-setup.js']
}
  1. 新建test/global-setup.js编写全局初始化逻辑:
const { initDataBase } = require('../src/db')
const config = require('../src/config/db')

beforeAll(async () => {
  global.sequelize = await initDataBase(config)
})

afterAll(async () => {
  await global.sequelize.drop()
  await global.sequelize.close()
})

配置后所有测试文件都会自动执行这组全局钩子,不用每个文件单独引入。

注意事项

Jest默认开启多进程并行执行测试,每个测试worker进程都会独立执行一遍setup逻辑。如果你需要全局只初始化一次数据库,可以在执行测试时添加--runInBand参数强制单进程执行,或者把数据库初始化逻辑放到Jest的globalSetup配置中,仅在所有测试启动前执行一次。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 22:54:00