如何使用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
相关产品推荐
相关产品推荐

