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

使用Jest和Enzyme测试React组件遇act警告及断言失败求助

问题排查与解决方案

你的问题核心在于异步操作未被act完整包裹,且Enzyme的组件状态未同步更新,导致断言时机错误和act警告。

问题根源

  1. 组件的onClick是异步函数,内部await getData()会将后续的setData和setIsLoading(false)放入微任务队列执行。你当前用void act()包裹的只是同步的点击触发,没有等待异步操作完成,React无法捕获后续的状态更新,因此抛出act警告。
  2. 异步操作完成后,Enzyme的mount wrapper不会自动刷新组件状态,你直接断言时拿到的还是旧的"loading"文本。

修复步骤

1. 将测试用例改为异步函数,用async/await配合act

需要用异步版的act包裹点击操作,并等待其完成,确保所有异步状态更新都被React捕获。

2. 同步Enzyme组件状态

异步操作完成后,调用component.update()刷新wrapper,确保获取到最新的组件DOM状态。

修改后的完整测试代码

import { mount } from 'enzyme';
import * as React from 'react';
import { act } from 'react-dom/test-utils';

const getData = async () => new Promise<string>((resolve) => resolve('data'));

const Component: React.FC = () => {
    const [data, setData] = React.useState('');
    const [isLoading, setIsLoading] = React.useState(true);

    const onClick = async () => {
        setIsLoading(true);

        try {
            const dataResponse = await getData();
            setData(dataResponse);
        } catch (error) {
            console.error('getData failed', error);
        }

        setIsLoading(false);
    };

    return (
        <button onClick={onClick}>
            <p>{isLoading ? 'loading' : data}</p>
        </button>
    );
};

describe('Component', () => {
    // 改为异步测试用例
    it('should render', async () => {
        const component = mount(<Component />);
        const button = component.find('button');
        let paragraph = component.find('p');

        expect(button).toBeDefined();
        expect(paragraph).toBeDefined();
        expect(paragraph.props().children).toBe('loading');

        // 用async/await包裹act,等待异步操作完成
        await act(async () => {
            button.simulate('click');
        });

        // 刷新组件状态
        component.update();
        // 重新获取最新的paragraph元素
        paragraph = component.find('p');

        expect(paragraph.props().children).toBe('data');
    });
});

额外说明

  • 如果你的项目中存在多个异步操作需要等待,也可以封装一个flushPromises函数来快速清空微任务队列:
    const flushPromises = () => new Promise(resolve => setImmediate(resolve));
    
    使用时在act之后调用await flushPromises(),再执行component.update()即可。
  • 确保你的Enzyme版本支持React 16+的act集成,若版本较旧可能需要安装enzyme-adapter-react-xx适配包并配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 17:16:29