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

使用Jest和Enzyme测试含API调用的React组件状态

如何用Jest和Enzyme测试React组件的状态变化

我来帮你一步步实现这个组件的状态测试~ 首先咱们得先把你提供的组件代码补全(你贴的render部分截断了),假设完整的组件代码是这样的:

import React, { Component } from 'react';

class App extends Component {
  constructor(props) {
    super(props);
    this.state = { isLoading: false };
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState({ isLoading: true });
    return fetch('https://api.github.com/users/londonappdev')
      .then(res => res.json())
      .then(data => {
        console.log(data);
        this.setState({ isLoading: false });
      });
  }

  render() {
    const { isLoading } = this.state;
    return (
      <div>
        <button onClick={this.handleClick} disabled={isLoading}>
          {isLoading ? '加载中...' : '获取数据'}
        </button>
      </div>
    );
  }
}

export default App;

接下来咱们分步骤完成测试:

第一步:安装必要依赖

根据你的React版本选择对应的Enzyme适配器(比如React 16用enzyme-adapter-react-16,React 17用@wojtekmaj/enzyme-adapter-react-17),同时安装fetch模拟工具:

npm install --save-dev enzyme enzyme-adapter-react-16 jest-fetch-mock
# 或用yarn
yarn add --dev enzyme enzyme-adapter-react-16 jest-fetch-mock

第二步:配置测试环境

在项目根目录的src文件夹下创建setupTests.js(Create React App会自动加载这个文件),配置Enzyme和全局fetch mock:

import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import fetchMock from 'jest-fetch-mock';

Enzyme.configure({ adapter: new Adapter() });
// 启用fetch的mock功能
fetchMock.enableMocks();

第三步:编写测试用例

创建App.test.js文件,编写以下测试逻辑,覆盖所有状态变化场景:

import React from 'react';
import { shallow } from 'enzyme';
import App from './App';

describe('App Component', () => {
  // 每次测试前重置fetch mock,避免测试间的干扰
  beforeEach(() => {
    fetch.resetMocks();
  });

  // 测试初始状态
  it('初始状态下isLoading为false,按钮显示正常文本', () => {
    const wrapper = shallow(<App />);
    expect(wrapper.state('isLoading')).toBe(false);
    expect(wrapper.find('button').text()).toBe('获取数据');
  });

  // 测试点击按钮后的即时状态变化
  it('点击按钮后立即将isLoading设为true,按钮显示加载文本', () => {
    const wrapper = shallow(<App />);
    wrapper.find('button').simulate('click');
    
    expect(wrapper.state('isLoading')).toBe(true);
    expect(wrapper.find('button').text()).toBe('加载中...');
    // 确认fetch被调用了正确的API地址
    expect(fetch).toHaveBeenCalledWith('https://api.github.com/users/londonappdev');
  });

  // 测试API请求完成后的状态变化
  it('API请求完成后将isLoading设为false,按钮恢复正常文本', async () => {
    // 模拟API返回的数据
    const mockUserData = { login: 'londonappdev', id: 123456 };
    fetch.mockResponseOnce(JSON.stringify(mockUserData));

    const wrapper = shallow(<App />);
    wrapper.find('button').simulate('click');

    // 等待异步的fetch请求完成
    await Promise.resolve();

    expect(wrapper.state('isLoading')).toBe(false);
    expect(wrapper.find('button').text()).toBe('获取数据');
  });
});

关键细节说明

  • shallow渲染:用shallow而非mount,因为我们只需要测试组件自身的状态变化,不需要渲染子组件(这里也没有子组件),能让测试更高效。
  • fetch mock:用jest-fetch-mock模拟网络请求,避免真实调用API,保证测试的稳定性和速度。
  • 异步测试处理:因为handleClick包含异步操作,所以用async/await等待Promise完成,确保状态更新后再执行断言,避免测试失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:59:50