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

React Redux组件单元测试遇Axios错误,求解决方案

React Redux Home组件单元测试Axios错误排查与解决

在为连接Redux的React Home组件编写单元测试时,持续遇到Axios相关错误。该组件用于展示数据、控制加载状态及错误弹窗显示,以下是组件代码、测试代码及错误截图,附上具体解决建议:

组件代码

import React, { FC, useEffect, useState } from 'react';
import { connect } from 'react-redux';
import { getRates } from '../store/action-creators/getRates';
import { Table, Button, Loading, Model } from 'components';
import { RootState } from 'store';
import { HomeProps } from './types/Home';
 
const Home: FC<HomeProps> = ({ rates, loading, error, getRates }) => {
    const [ showErrorModal, setShowErrorModal ] = useState<boolean>(false);

    useEffect(
        () => {
            if (error) {
                setShowErrorModal(true);
            }
        },
        [ error ]
    );

    const handleCloseErrorModal = () => {
        setShowErrorModal(false);
    };

    return (
        <div className="home">
            <Button onClick={getRates} />
            {loading ? <Loading /> : <Table rates={rates} />}
            {showErrorModal && <Model message={error} onClose={handleCloseErrorModal} />}
        </div>
    );
};

const mapStateToProps = (state: RootState) => ({
        rates: state.rates.rates,
        loading: state.rates.loading,
        error: state.rates.error
    }
);

const mapDispatchToProps = {
    getRates
};

const connector = connect(mapStateToProps, mapDispatchToProps) as any;

export default connector(Home);

测试代码

import React from 'react';
import { render, fireEvent, waitFor } from '@testing-library/react';
import { Provider } from 'react-redux';
import configureStore from 'redux-mock-store';
import Home from '../Home';
import { getRates } from '../../store/action-creators/getRates';

const mockStore = configureStore();

describe('Home component', () => {
  it('renders correctly when loading is true', () => {
    const initialState = {
      rates: {
        loading: true,
      },
    };

    const store = mockStore(initialState);
    const { getByTestId } = render(
      <Provider store={store}>
        <Home />
      </Provider>
    );

    const loadingElement = getByTestId('loading');
    expect(loadingElement).toBeInTheDocument();
  });

  it('renders correctly when loading is false', () => {
    const initialState = {
      rates: {
        loading: false,
        rates: {
          USD: 1.0808,
          JPY: 158.35,
        },
      },
    };

    const store = mockStore(initialState);
    const { getByTestId } = render(
      <Provider store={store}>
        <Home />
      </Provider>
    );

    const tableElement = getByTestId('rates-table');
    expect(tableElement).toBeInTheDocument();
  });

  it('displays error modal when error is not null', async () => {
    const initialState = {
      rates: {
        loading: false,
        error: 'Network error',
      },
    };

    const store = mockStore(initialState);
    const { getByTestId, getByText } = render(
      <Provider store={store}>
        <Home />
      </Provider>
    );

    const errorButtonElement = getByTestId('error-button');
    fireEvent.click(errorButtonElement);

    const errorModalElement = await waitFor(() => getByTestId('error-modal'));
    expect(errorModalElement).toBeInTheDocument();

    const errorMessageElement = getByText('Network error');
    expect(errorMessageElement).toBeInTheDocument();
  });

  it('dispatches getRates action when button is clicked', () => {
    const initialState = {
      rates: {
        loading: false,
      },
    };

    const store = mockStore(initialState);
    store.dispatch = jest.fn();

    const { getByTestId } = render(
      <Provider store={store}>
        <Home />
      </Provider>
    );

    const buttonElement = getByTestId('get-rates-button');
    fireEvent.click(buttonElement);

    expect(store.dispatch).toHaveBeenCalledWith(getRates());
  });
});

错误截图

Axios测试错误

解决建议

1. Mock Axios避免实际网络请求

错误根源是getRates action creator中使用Axios发送真实请求,测试时需mock整个Axios模块,阻止真实请求发送。在测试文件最顶部添加:

jest.mock('axios'); // 假设getRates依赖axios

2. 配置Redux中间件处理异步Action

如果getRates是异步Action(比如使用redux-thunk),redux-mock-store默认不处理异步逻辑,需添加thunk中间件:

import thunk from 'redux-thunk';
const mockStore = configureStore([thunk]); // 初始化mockStore时加入thunk

也可直接mockgetRates的实现简化测试:

jest.mock('../../store/action-creators/getRates', () => ({
  getRates: jest.fn(() => ({ type: 'GET_RATES' }))
}));

3. 修正错误弹窗测试用例逻辑

原测试中点击error-button是错误的,组件会在error存在时通过useEffect自动打开弹窗,无需手动触发。修改该测试:

it('displays error modal when error is not null', async () => {
  const initialState = {
    rates: {
      loading: false,
      error: 'Network error',
      rates: {} // 补充缺失字段,避免组件报错
    },
  };

  const store = mockStore(initialState);
  const { getByTestId, getByText } = render(
    <Provider store={store}>
      <Home />
    </Provider>
  );

  // 直接等待弹窗渲染
  const errorModalElement = await waitFor(() => getByTestId('error-modal'));
  expect(errorModalElement).toBeInTheDocument();

  const errorMessageElement = getByText('Network error');
  expect(errorMessageElement).toBeInTheDocument();
});

4. 完善测试用例的InitialState

确保每个测试用例的initialState包含组件用到的所有字段(rates、loading、error),避免组件解构props时出现undefined:

// 示例:完善加载状态测试的initialState
const initialState = {
  rates: {
    loading: true,
    rates: {},
    error: null
  },
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 06:34:53