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

如何在React组件测试中阻止useEffect内的Redux Dispatch触发请求

问题

我有一个React组件,当状态为"idle"时显示骨架屏,同时通过react-redux的dispatch发起请求获取数据。编写该组件的测试文件时,我希望渲染骨架屏并验证其是否正常渲染,但由于mock store的状态为"idle",渲染组件时触发了dispatch,进而出现错误:Unknown Error: Error: Error: connect ECONNREFUSED 127.0.0.1:443。请问如何避免该dispatch以阻止测试中的请求?

简化后的组件代码

export default function MyComponent() {
    const dispatch = useAppDispatch();

    [...]

    useEffect(() => {
        if ("idle" === status) {
            // my query

            dispatch(fetchData(query));
        }
    }, [dispatch]);

    if ("idle" === status) {
        return <MyComponentSkeleton />;
    }

测试代码

describe("MyComponent component", () => {
    let store: ReturnType<typeof createMockStore>;

    it("renders correctly when status is IDLE", () => {
        store = createMockStore();

        render(
            <Provider store={store}>
                <MyComponent />
            </Provider>
        );

        const skeletonElement = screen.getByTestId("my-component-skeleton");
        expect(skeletonElement).toBeInTheDocument();
    });
解决方案

方法1:Mock fetchData action creator

直接在测试文件中mock掉fetchData,让它返回一个空的action,避免实际触发请求逻辑:

// 假设fetchData在./actions文件中导出
jest.mock('./actions', () => ({
  ...jest.requireActual('./actions'),
  fetchData: jest.fn(() => ({ type: 'MOCK_FETCH_DATA' }))
}));

describe("MyComponent component", () => {
    let store: ReturnType<typeof createMockStore>;

    it("renders correctly when status is IDLE", () => {
        store = createMockStore();

        render(
            <Provider store={store}>
                <MyComponent />
            </Provider>
        );

        const skeletonElement = screen.getByTestId("my-component-skeleton");
        expect(skeletonElement).toBeInTheDocument();
        // 可选:验证fetchData是否被正确调用
        expect(fetchData).toHaveBeenCalled();
    });
});

方法2:通过初始状态跳过请求触发

如果组件中的status来自redux store,可先设置初始状态为非"idle",渲染后再更新为"idle",这样就能绕过useEffect的请求触发逻辑:

describe("MyComponent component", () => {
    let store: ReturnType<typeof createMockStore>;

    it("renders correctly when status is IDLE", () => {
        // 初始状态设为非idle,避免组件挂载时触发请求
        store = createMockStore({ yourSliceName: { status: 'loading' } });

        render(
            <Provider store={store}>
                <MyComponent />
            </Provider>
        );

        // 更新状态为idle,此时组件渲染骨架屏,但useEffect不会重复触发(依赖仅为dispatch)
        store.dispatch({ type: 'yourSliceName/setStatus', payload: 'idle' });

        const skeletonElement = screen.getByTestId("my-component-skeleton");
        expect(skeletonElement).toBeInTheDocument();
    });
});

方法3:拦截底层网络请求

如果不想改动action或store状态,可直接拦截fetch或axios等请求工具,从根源阻止请求发送:

拦截axios:

jest.mock('axios', () => ({
  get: jest.fn(() => Promise.resolve({ data: {} }))
}));

拦截全局fetch:

global.fetch = jest.fn(() => 
  Promise.resolve({
    json: () => Promise.resolve({}),
    ok: true,
  })
) as jest.Mock;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 05:44:55