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

单元测试无法执行完成:act包裹渲染后定时器持续运行

问题分析与修复方案

问题描述

初始化阶段,由getManagedEntries模拟函数触发的状态变更导致了“test was not wrapped in act (...)”错误。但将render放入act()中后,测试无法执行完成,定时器持续运行。相关测试代码如下:

it('should render without crashing', async () => {
    (getManagedEntries as jest.MockedFunction<typeof getManagedEntries>).mockImplementation(() => {
        return Promise.resolve(getManagedEntriesData) as any;
    });

    await act(async () => {
        render(<SegmentDropdown config={configForSegmentDropdown} depth={1} root={true} segment={'test'} />, {
            wrapper,
        });
    });

    waitFor(() => {
        //ignore this useless test which is for the sake of simplicity > I just needs this test to resolve
        expect(true).toBeTruthy();
    });
});

核心问题

  1. React Testing Library的render方法本身已经被act自动包裹,手动嵌套act会干扰异步状态更新的处理逻辑,导致Promise无法正确resolve。
  2. waitFor没有使用await,测试会直接跳过等待逻辑,同时组件内未清理的定时器会一直运行,导致测试卡住。

修复步骤

1. 移除手动的act包裹

直接删除外层的await act(...),让render自己处理内部的状态更新。

2. 正确等待异步操作

给waitFor加上await,确保测试等待组件内的异步请求和状态更新完成后再结束。哪怕是临时的空断言,也必须通过await让测试流程正确等待。

3. 清理定时器(关键)

如果组件内部使用了定时器,测试结束后要手动清理,避免定时器持续运行导致测试卡住。可以用jest.clearAllTimers(),或者提前启用假定时器并在测试后恢复。

修复后的代码

it('should render without crashing', async () => {
    // 简化mock写法,用mockResolvedValue替代mockImplementation
    (getManagedEntries as jest.MockedFunction<typeof getManagedEntries>).mockResolvedValue(getManagedEntriesData as any);

    // 直接render,不需要手动包act
    render(<SegmentDropdown config={configForSegmentDropdown} depth={1} root={true} segment={'test'} />, {
        wrapper,
    });

    // 必须await waitFor,确保异步操作完成
    await waitFor(() => {
        // 建议替换成真实的组件渲染断言,比如检查某个下拉元素是否存在
        expect(true).toBeTruthy();
    });

    // 清理定时器,防止测试卡住
    jest.clearAllTimers();
});

额外优化(针对定时器场景)

如果组件依赖定时器,还可以在测试前后切换假定时器:

beforeEach(() => {
    jest.useFakeTimers();
});

afterEach(() => {
    jest.useRealTimers();
});

内容的提问来源于stack exchange,提问作者San Jay Falcon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 02:09:21