普通网友 2025-08-21 01:55 采纳率: 97.6%
浏览 0
已采纳

Cannot log after tests are done. Did you forget to wait for something async?

**问题描述:** 在使用 Jest 或其他 JavaScript 测试框架进行单元测试时,开发者可能会遇到如下警告信息:`Cannot log after tests are done. Did you forget to wait for something async?`。该问题通常出现在异步操作未正确等待的情况下,例如未使用 `await` 或 `.then()` 处理 Promise,导致日志输出或断言发生在测试生命周期之外。此类问题可能掩盖实际的测试失败原因,甚至造成误判。理解异步编程机制及测试框架的执行顺序,是解决此问题的关键。
  • 写回答

1条回答 默认 最新

  • 关注

    一、问题现象与初步理解

    在使用 Jest 或其他 JavaScript 测试框架进行单元测试时,开发者可能会遇到如下警告信息:

    CANNOT_LOG_AFTER_TESTS_DONE: Cannot log after tests are done. Did you forget to wait for something async?

    该警告通常出现在测试函数执行完毕后仍有异步操作继续执行并尝试输出日志或进行断言。例如:

    test('async test without await', async () => {
      setTimeout(() => {
        console.log('This will cause warning');
        expect(true).toBe(true);
      }, 100);
    });

    上述代码中,测试函数提前返回,但异步操作(setTimeout)在之后才执行,导致 Jest 无法正确捕获断言结果,从而触发警告。

    二、异步编程基础与测试执行顺序

    Jest 默认将测试视为同步操作。如果测试中包含异步代码,必须显式告知 Jest 需要等待异步操作完成。

    • 使用 async/await 是最常见的方式。
    • 也可以通过返回一个 Promise 或使用 done() 回调函数。

    错误示例(未等待异步操作):

    test('wrong async usage', () => {
      fetchSomething().then(() => {
        expect(true).toBe(true);
      });
    });

    正确示例(等待异步操作完成):

    test('correct async usage with await', async () => {
      await fetchSomething();
      expect(true).toBe(true);
    });

    三、问题定位与调试方法

    遇到该警告时,应重点检查以下方面:

    1. 是否所有异步操作都使用了 await.then()
    2. 是否在 setTimeoutsetInterval 或第三方异步函数中执行了断言。
    3. 是否使用了未 resolve 的 Promise。

    可以使用以下方式辅助调试:

    • 添加 console.log 输出异步操作的执行顺序。
    • 使用 Jest 的 jest.useFakeTimers()jest.runAllTimers() 控制异步流程。

    四、解决方案与最佳实践

    解决此类问题的核心在于确保异步操作在测试生命周期内完成,并正确等待其结果。

    写法说明是否推荐
    async/await清晰、现代、易于维护✅ 推荐
    .then().catch()兼容性好,但可读性略差✅ 推荐
    done() 回调旧版 API,容易出错❌ 不推荐
    test('using async/await correctly', async () => {
      const result = await fetchData();
      expect(result).toBe('success');
    });

    五、深入理解 Jest 的异步执行机制

    Jest 内部通过 Promise 链追踪测试的执行状态。当测试函数返回 Promise,Jest 会等待其 resolve 或 reject。否则,测试会被视为已完成。

    流程图如下:

    graph TD A[Test Function Starts] --> B{Is Async?} B -->|Yes| C[Returns Promise] B -->|No| D[Immediately Resolves] C --> E[Wait for Resolve/Reject] D --> F[Test Ends Immediately] E --> G[Test Ends after Async]

    因此,任何未等待的异步操作都可能导致断言或日志发生在测试生命周期之外,从而触发警告。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 已采纳回答 10月23日
  • 创建了问题 8月21日