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

Jest运行npm run jest时异步回调内测试用例未被识别报错

问题根因

Jest 运行测试分为两个独立阶段:

  • 测试收集阶段:同步执行所有describe回调,收集所有同步声明的it/test用例,该阶段不会等待任何异步回调执行。
  • 测试执行阶段:按顺序运行收集到的用例、执行对应生命周期钩子,这个阶段才支持等待异步操作完成。

你将it测试用例写在hgetall的异步回调内,等Redis异步IO返回、回调触发准备注册用例时,Jest早已完成测试收集流程,没有识别到任何测试用例,因此抛出Your test suite must contain at least one test错误。从你加的debug日志也能验证时序问题:debug2会在测试收集阶段打印,debug3到debug6要等Redis操作返回才会执行,完全赶不上测试用例注册的时间窗口。

修复方案

核心原则:所有it测试用例必须在describe回调内同步声明,异步逻辑全部放到测试用例内部,或者beforeAll/beforeEach这类官方提供的生命周期钩子中处理。

修复后的可运行代码示例:

const { promisify } = require('util');

describe("some testing", () => {
  describe("redisProcessor", () => {
    let queryResult;
    let isContentMatch = true;
    // 将回调形式的hgetall包装为Promise形式,方便用async/await控制时序
    const hgetallAsync = promisify(aisListenerSpec.redisSetter.client.hgetall)
      .bind(aisListenerSpec.redisSetter.client);

    // 所有前置异步操作放到beforeAll钩子中,等待全部执行完成后再运行测试用例
    beforeAll(async () => {
      aisListenerSpec.run("123456");
      // 如果redisProcessor是异步写入方法,必须加await等待写入完成再查询
      await aisListenerSpec.redisProcessor(JSON.stringify(validMessage));
      // 等待Redis查询结果返回
      queryResult = await hgetallAsync("________someString______");

      // 提前做字段比对
      for (const key in queryResult) {
        if (validMessage[key] !== undefined && JSON.stringify(validMessage[key]) !== queryResult[key]) {
          isContentMatch = false;
        }
      }
    });

    // 所有it用例同步注册,Jest在收集阶段可以正常识别
    it("________someString______${missionId} should contain 2 required fields: messageTime and missionId", () => {
      expect(queryResult["messageTime"]).toBeTruthy();
      expect(queryResult["missionId"]).toBe("123456");
    });

    it("________someString______${missionId} fields should match validMessage", () => {
      expect(isContentMatch).toBeTruthy();
    });
  });
});
注意事项
  • 如果你使用的是ioredis、或4.0以上版本的node-redis客户端,原生支持Promise返回,不需要手动做promisify包装,直接await对应方法即可。
  • 不要在describe回调的最外层直接执行数据库写入、查询这类带IO的异步操作,这类有副作用的逻辑统一放到生命周期钩子或测试用例内部,避免和Jest的执行时序冲突。
  • 如果不想用async/await语法,也可以用Jest提供的done回调处理异步逻辑,只要保证it本身是同步注册的即可,示例如下:
it("verify redis data with done callback", (done) => {
  aisListenerSpec.redisSetter.client.hgetall("________someString______", (err, result) => {
    expect(result.missionId).toBe("123456");
    // 异步操作完成后必须调用done,否则Jest会等待超时
    done();
  });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 15:06:22