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

React组件Axios调用单元测试中Sinon Stub未生效问题

使用Sinon Sandbox Mock Axios测试React组件的API调用场景

你是不是在测试React组件里setState回调中调用Axios发起请求的逻辑呀?我看你已经用Sinon Sandbox写了基础的Stub,但可能需要调整几个点才能让测试准确覆盖到目标代码,下面给你梳理下关键步骤和注意事项:

先看你当前的Stub代码

你现在写的是Stub Axios的get方法:

sandbox1 = sandbox.create(); 
const resolved = new Promise((r) => r([{ id: 1, name: 'PetA' }, { id: 2, name:'PetB' }])); 
sandbox1.stub(axios, 'get').returns(resolved);

但你要测试的代码里调用的是axios(req)(直接调用Axios默认函数),不是axios.get,所以这个Stub不会匹配到你的请求调用,得调整Stub目标。

调整Stub匹配axios(req)调用

因为axios(req)是调用Axios的默认导出函数,所以要把Stub目标改成Axios默认函数本身,同时模拟真实的Axios响应结构(Axios响应会包裹在data字段里):

// 创建模拟成功响应的Promise
const mockResponse = Promise.resolve({ 
  data: [{ id: 1, name: 'PetA' }, { id: 2, name:'PetB' }] 
});
// Stub Axios默认函数
sandbox1.stub(axios, 'default').returns(mockResponse);
// 如果你的导入方式是import axios from 'axios',也可以直接这么写:
// sandbox1.stub(axios).returns(mockResponse);

处理React异步setState的测试时机

setState的回调是异步执行的,测试时必须等待回调执行完毕再做断言。这里推荐用async/await配合测试库的等待方法,比如React Testing Library的waitFor,或者Enzyme里的setImmediate:

示例测试用例(以React Testing Library为例)

import { render, screen, waitFor } from '@testing-library/react';
import YourComponent from './YourComponent';
import axios from 'axios';
import sinon from 'sinon';

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

  beforeEach(() => {
    sandbox1 = sinon.createSandbox();
  });

  afterEach(() => {
    sandbox1.restore(); // 清理Sandbox,避免污染其他测试
  });

  test('setState回调中调用Axios请求成功后更新状态', async () => {
    // 1. 准备Mock数据和Stub
    const mockData = [{ id: 1, name: 'PetA' }, { id: 2, name:'PetB' }];
    sandbox1.stub(axios, 'default').resolves({ data: mockData });

    // 2. 渲染组件并触发触发setState的动作(比如点击按钮)
    render(<YourComponent />);
    screen.getByText('触发请求').click();

    // 3. 等待异步操作完成并断言
    await waitFor(() => {
      // 断言Axios被调用了一次
      expect(axios.default.calledOnce).toBe(true);
      // 断言UI渲染结果(用状态驱动的UI更易断言)
      expect(screen.getByText('PetA')).toBeInTheDocument();
      expect(screen.getByText('PetB')).toBeInTheDocument();
    });
  });
});

额外:模拟请求失败场景

如果要测试错误处理逻辑,只需要Stub返回rejected的Promise即可:

sandbox1.stub(axios, 'default').rejects(new Error('请求超时'));
// 然后断言组件是否正确处理错误,比如显示错误提示
await waitFor(() => {
  expect(screen.getByText('请求超时')).toBeInTheDocument();
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:15:11