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

React单元测试中如何mock异步方法并验证回调入参为更新后的state值

核心问题分析
  • 原组件执行顺序错误:getData是异步方法,then回调属于微任务,会在同步代码执行完成后才触发。原代码中foo(this.state.data)是同步执行的,此时setState还未运行,拿到的永远是data的初始值,和测试逻辑无关。
  • 测试代码逻辑缺陷:
    1. jest.mock直接赋值给serviceObj的用法错误,jest.mock是模块级别 mock 声明,不会返回 mock 后的模块实例,需要通过导入获取 mock 后的对象
    2. 未等待异步逻辑执行完成就直接断言,此时异步请求、状态更新的逻辑都未运行
    3. 未对foo方法做 mock 配置,无法捕获它的调用参数
修复步骤

1. 修正组件业务逻辑

要让foo在state更新完成后调用,可以把foo放到setState的第二个回调参数中(setState第二个回调会在状态更新、组件重渲染完成后触发):

componentDidMount() {
  serviceObj.getData().then(response => {
    this.setState({data: response.data}, () => {
      // 此时state已经更新完成,拿到的是最新值
      foo(this.state.data);
    });
  });
}

2. 修正单元测试用例

需要先完成foo和服务模块的 mock,再用waitFor等待异步逻辑执行完成后再断言:

// 顶部先做模块mock,注意jest.mock要放在模块导入之前
// 假设foo从fooModule导入,根据实际路径修改
jest.mock('path/to/fooModule', () => ({
  __esModule: true,
  default: jest.fn()
}));
// mock服务模块
jest.mock('serviceModule', () => ({
  __esModule: true,
  default: {
    getData: jest.fn(() => Promise.resolve({data: "test"}))
  }
}));

// 导入依赖
import { render, waitFor } from '@testing-library/react';
import foo from 'path/to/fooModule';
import MyComponent from './MyComponent';

it('调用foo时传入接口返回的最新data值', async () => {
  render(<MyComponent />);

  // 等待异步逻辑执行完成,确认foo调用参数符合预期
  await waitFor(() => {
    expect(foo).toHaveBeenCalledWith("test");
  });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 23:27:00