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

如何使用Mocha模拟API调用测试依赖API响应的React组件?

当然可以!完全不用实际调用API就能模拟响应,我来给你详细讲清楚怎么解决这个问题——既搞定fetch is not defined的错误,又能精准控制API返回的数据。

核心思路

你的问题本质是两个:测试环境缺少浏览器的fetch API,以及需要mock异步API的响应。我们可以通过全局mock fetch函数一举解决这两个问题,不用导入isomorphic-fetch。

方案一:手动Mock全局fetch(无需额外库)

如果你不想引入新的依赖,可以直接在测试文件里手动给global对象添加mock版的fetch,还能在不同测试用例里灵活切换成功/失败场景:

import { mount } from 'enzyme';
import YourComponent from './YourComponent';

describe('YourComponent', () => {
  // 保存原始fetch,测试后恢复
  let originalFetch;

  beforeEach(() => {
    originalFetch = global.fetch;
  });

  afterEach(() => {
    global.fetch = originalFetch;
  });

  it('挂载后调用API并设置正确状态', async () => {
    // 模拟API成功响应
    global.fetch = () => 
      Promise.resolve({
        ok: true,
        json: () => Promise.resolve({ username: 'mockUser', email: 'mock@test.com' })
      });

    // 挂载组件
    const wrapper = mount(<YourComponent />);

    // 等待异步请求完成(让Promise进入resolved状态)
    await Promise.resolve();
    // 更新组件,让异步状态更新同步到Enzyme的wrapper
    wrapper.update();

    // 断言状态是否正确设置
    expect(wrapper.state('user')).toEqual({
      username: 'mockUser',
      email: 'mock@test.com'
    });
  });

  it('API请求失败时设置错误状态', async () => {
    // 模拟API失败
    global.fetch = () => Promise.reject(new Error('请求超时'));

    const wrapper = mount(<YourComponent />);
    await Promise.resolve();
    wrapper.update();

    expect(wrapper.state('error')).toBe('请求超时');
  });
});

方案二:用Sinon做更灵活的Mock(推荐)

如果你需要更强大的mock能力(比如断言fetch是否被调用、调用次数、传入的参数等),可以用sinon这个常用的测试工具库:

  1. 先安装依赖:
npm install sinon --save-dev
  1. 测试代码示例:
import { mount } from 'enzyme';
import sinon from 'sinon';
import YourComponent from './YourComponent';

describe('YourComponent', () => {
  let fetchMock;

  // 每个测试前创建fetch的mock
  beforeEach(() => {
    fetchMock = sinon.stub(global, 'fetch');
  });

  // 每个测试后恢复原始fetch,避免影响其他测试
  afterEach(() => {
    fetchMock.restore();
  });

  it('正确调用API地址并处理响应', async () => {
    // 设置mock返回的响应数据
    const mockResponse = { id: 1, name: 'Mock Data' };
    fetchMock.resolves({
      json: () => Promise.resolve(mockResponse)
    });

    const wrapper = mount(<YourComponent />);
    await Promise.resolve();
    wrapper.update();

    // 断言fetch是否被正确调用(检查请求URL)
    expect(fetchMock.calledWith('https://your-api-url.com/data')).toBe(true);
    // 断言状态更新正确
    expect(wrapper.state('data')).toEqual(mockResponse);
  });
});

关键注意点

  • 异步处理:因为fetch是异步操作,挂载组件后不能立刻断言状态,需要用await Promise.resolve()或setImmediate等待事件循环完成,再调用wrapper.update()让Enzyme同步组件状态。
  • shallow渲染的特殊情况:如果用shallow渲染,默认不会自动执行componentDidMount,你需要手动调用wrapper.instance().componentDidMount()来触发API调用,之后同样要处理异步更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:11:12