You need to enable JavaScript to run this app. 如何用Jest实现含共享异步依赖的多Getter测试套件架构
优惠活动
大模型
产品
解决方案
定价
更多

如何用Jest实现含共享异步依赖的多Getter测试套件架构

问题梳理

我已经查阅了Jest官方网站上的所有指南和示例,但并未找到能够解答我问题的内容。
我希望找到一种模式,能够使用Jest单独运行多个不同函数(我的场景中为getter)的测试用例。
目前,我的example.test.ts文件中代码如下:

import { getterOne, getterTwo, getterThree, ... } from getters;

describe('test suite', () => {
  beforeAll(async () => {
    //connect to MongoDB
  })

  afterAll(async () => {
    //disconnect from MongoDB
  })

  //request token from DB, to check it
  it('key', async () => {
    const key = await KeysModel.findOne({_id: 'any'}).lean();
    expect(key).toMatchSnapshot({
      field: expect.any(String),
    });
  });

  /**
   * predefine key and some other things
   * but I can't call key here, because describe doesn't support
   * async/await, as it should be synchronous
   */

  //test separate getterOne with key variable as an argument
  //test separate getterTwo with key variable as an argument
  //test separate getterThree with key variable as an argument
})

我发现无法在后续的it用例中使用此前定义的key。如果在顶层重新定义key,会存在以下问题:

  • 为每个getter测试用例重新定义key变量是否合适?如果我有大量getter,将会产生xN次完全无用的重复请求。
  • 据我所知,我无法在describe内部使用async/await,因为Jest不支持从"describe"返回Promise,测试必须同步定义。

我并非询问具体的代码编写方法,而是询问这类场景下编写存在依赖关系的测试用例的正确模式是什么。
能否提供相关示例?我应该在describe中编写更多test用例,还是有其他通用的最佳实践?应该使用哪些Jest方法、以什么顺序使用?

目前我通过let关键字声明空变量,并按如下方式使用:

describe('test suite', () => {
  beforeAll(async () => {
    //connect to MongoDB
  })

  afterAll(async () => {
    //disconnect from MongoDB
  })

  describe('inside', () => {
    let key;

    beforeAll(async () => {
      key = await KeyModel.findOne();
    })
   
    test('getterOne', async () => {
      const res = await getterOne(key);
      expect(res).toMatchSnapshot({
        id: expect.any(Number)
      });
    });

    //other test with keys..
  
  })
})

这种写法是否被认为是良好实践?

解答内容
  • 你当前使用的「嵌套describe + 作用域内let声明变量 + beforeAll异步赋值依赖」的写法,本身就是Jest官方推荐的共享测试前置依赖的标准模式,完全属于良好实践。
    这种写法的核心逻辑是匹配Jest的测试执行生命周期:所有测试文件的执行分为两个阶段,第一阶段是同步遍历整个文件,收集所有describe、test/it的定义,第二阶段才按照注册顺序执行对应的钩子和测试用例。因此你完全不需要在describe回调里直接await拿数据,只需要在对应作用域的beforeAll钩子里完成异步依赖的初始化,同作用域下的所有测试用例运行时,就能拿到已经准备完成的依赖值。
    这种模式完全避免了每个测试用例重复请求数据库拉取key的问题,同一个嵌套作用域下的所有测试,只会执行一次beforeAll里的key查询操作。
  • 几个常见误区澄清:
    • Jest确实不支持在describe回调中直接返回Promise,也不允许在describe顶层直接写await,这是因为测试收集阶段必须是同步执行的,如果在顶层阻塞等待异步操作,会打乱整个测试收集流程,导致后续测试用例无法被正常识别。
    • 你之前把查询key的操作写在独立it测试用例里的写法存在局限性:虽然测试用例默认按从上到下的顺序执行,但每个it用例都是独立的函数作用域,内部定义的局部变量无法被其他测试用例访问到。
  • 可优化的细节参考:
    • 如果你需要校验key本身的正确性,完全可以在拉取key的同一个beforeAll钩子里做断言,不需要单独占一个it用例。比如在key = await KeyModel.findOne();之后直接写expect(key).toBeTruthy(),如果key拉取失败,整个作用域下的所有测试都会直接失败,省去单独写一个key校验用例的冗余。
    • 如果你有部分getter测试不需要依赖key参数,还可以进一步拆分describe作用域,把不需要依赖的测试和需要key的测试隔离开,避免无意义的前置操作拖慢整体测试执行速度。
    • 如果后续依赖的参数变多,可以直接把这部分共享的前置逻辑抽成可复用的工具函数,减少重复代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.29 08:45:04