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

如何用Enzyme和Jest测试React组件加载状态下显示Downloading...文本

问题概述

我有一个名为ChoiceOfFundForm的React组件,包含下载按钮。点击按钮会触发handleClick函数,将loading状态设为true并调用downloadChoiceOfFund动作;下载完成或出错后,loading会重置为false。

我需要编写测试用例,确保loading为true时,组件能通过DownloadingContainer正确显示...Downloading文本。使用Enzyme和Jest测试时,出现错误:TypeError: expect(...).text is not a function。

组件核心代码:

const DownloadingContainer = styled('div')({
    color: 'rgb(92, 111, 123)',
});

const ChoiceOfFundForm = ({
    // props and state definitions
}) => {
    // ...

    return (
        <>
            <div style={{ display: 'flex', alignItems: 'center' }}>
                <ContributionFormLink
                    // props
                    onClick={handleClick}
                />
                {loading && (
                    <DownloadingContainer data-testid="downloadingContainer">
                        ...Downloading
                    </DownloadingContainer>
                )}
            </div>
        </>
    );
};

失败的测试代码:

jest.mock('react', () => ({
...jest.requireActual('react'),
useState: (initialState) => [initialState, mockSetLoading],
}));

it('should show "Downloading..." text when loading state is true', () => {
    mockSetLoading(true);
    const wrapper = shallow(<ChoiceOfFundForm store={store} />).dive();
    const downloadingContainer = wrapper.find('[data-testid="downloadingContainer"]');

    expect(downloadingContainer).text().toEqual('...Downloading');
});
错误原因
  1. 断言写法错误:text()是Enzyme ShallowWrapper实例的方法,不能直接在expect()返回的断言对象上调用。正确顺序是先调用wrapper的text()获取内容,再传给expect()做断言。
  2. 状态模拟方式错误:直接调用mockSetLoading(true)无法正确触发组件重新渲染,因为组件已经完成初始渲染,mock的useState不会自动更新组件状态。
解决方案

1. 修正断言写法

将错误的断言代码:

expect(downloadingContainer).text().toEqual('...Downloading');

改为:

expect(downloadingContainer.text()).toEqual('...Downloading');

2. 正确模拟loading状态

根据loading的来源(组件内部state或Redux store),选择对应的模拟方式:

情况1:loading是组件内部state

使用Enzyme的setState方法直接更新组件状态,并触发重新渲染:

it('should show "...Downloading" text when loading state is true', () => {
    const wrapper = shallow(<ChoiceOfFundForm store={store} />).dive();
    // 设置组件内部loading为true
    wrapper.setState({ loading: true });
    // 手动触发组件更新(部分Enzyme版本会自动更新,此步骤可选)
    wrapper.update();

    const downloadingContainer = wrapper.find('[data-testid="downloadingContainer"]');
    // 先验证元素存在
    expect(downloadingContainer.exists()).toBe(true);
    // 验证文本内容
    expect(downloadingContainer.text()).toEqual('...Downloading');
});

情况2:loading来自Redux store

初始化mockStore时传入loading: true的状态,确保组件渲染时能获取到正确的状态:

import configureMockStore from 'redux-mock-store';

const mockStore = configureMockStore();
// 初始化包含loading: true的store
const store = mockStore({
    // 其他必要的state字段
    loading: true
});

it('should show "...Downloading" text when loading state is true', () => {
    const wrapper = shallow(<ChoiceOfFundForm store={store} />).dive();
    const downloadingContainer = wrapper.find('[data-testid="downloadingContainer"]');

    expect(downloadingContainer.exists()).toBe(true);
    expect(downloadingContainer.text()).toEqual('...Downloading');
});

3. 移除不必要的useState mock

之前mock React useState的代码会干扰组件正常的状态管理,建议移除该mock,改用上述方式模拟状态。

完整修正后的测试示例(内部state场景)
import { shallow } from 'enzyme';
import ChoiceOfFundForm from './ChoiceOfFundForm';

it('should display "...Downloading" when loading is true', () => {
    const wrapper = shallow(<ChoiceOfFundForm store={store} />).dive();
    
    // 更新loading状态
    wrapper.setState({ loading: true });
    wrapper.update();

    const downloadingContainer = wrapper.find('[data-testid="downloadingContainer"]');
    
    expect(downloadingContainer.exists()).toBe(true);
    expect(downloadingContainer.text().trim()).toEqual('...Downloading');
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 12:03:21