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

如何使用Jest Mock Ajax请求的Promise并解决done方法不存在报错?

错误根因

业务代码中request.fetch的返回值是jQuery AJAX返回的Deferred对象,自带done()、fail()链式回调方法;但测试代码中你Mock返回的是标准ES6 Promise,标准Promise仅支持then()、catch(),不存在done、fail方法,因此调用时抛出类型错误。

解决方案

直接Mock返回符合jQuery Deferred接口的对象,手动实现done、fail方法即可,同时可根据测试场景选择触发成功/失败回调:

1. 提前Mock整个request模块(更稳定,避免导入真实代码)

在测试文件顶部加入如下代码,先完成模块Mock再导入:

// 优先Mock整个request模块
jest.mock('request', () => ({
  fetch: jest.fn(),
  create: jest.fn()
}))
import * as request from "request";

2. 根据测试场景自定义返回值

测试请求成功场景

test('fetchDuplicateRecords 成功时正确设置state', () => {
  // 构造你需要的 mock 返回数据
  const mockDuplicateRecords = [{id: 1, name: '测试数据'}];

  // 重写fetch的Mock返回
  request.fetch.mockReturnValue({
    done: (callback) => {
      // 触发成功回调,传入模拟响应
      callback(mockDuplicateRecords);
      // 返回自身支持链式调用
      return this;
    },
    fail: () => {
      // 成功场景无需触发失败回调,空实现即可
      return this;
    }
  })

  // 调用组件方法,这里以Enzyme shallow挂载为例
  const wrapper = shallow(<PeopleForm />);
  wrapper.instance().fetchDuplicateRecords();

  // 断言state符合预期
  expect(wrapper.state('duplicateRecords')).toEqual(mockDuplicateRecords);
  expect(wrapper.state('showDuplicateRecords')).toBe(true);
})

测试请求失败场景

test('fetchDuplicateRecords 失败时正确清空重复记录', () => {
  request.fetch.mockReturnValue({
    done: () => {
      return this;
    },
    fail: (callback) => {
      // 触发失败回调
      callback();
      return this;
    }
  })

  const wrapper = shallow(<PeopleForm />);
  // 可以先设置初始state有值,验证失败后被清空
  wrapper.setState({duplicateRecords: [{id: 1, name: '旧数据'}]});
  wrapper.instance().fetchDuplicateRecords();

  expect(wrapper.state('duplicateRecords')).toEqual([]);
})

可选优化建议

如果后续想兼容标准Promise用法,可以将业务代码中的.done()替换为.then()、.fail()替换为.catch(),jQuery的Deferred对象本身也兼容这两个标准方法,后续Mock时直接返回Promise即可,无需额外实现自定义方法。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 23:06:01