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

使用Jest手动模拟API遇阻:问题排查与实现指导

解决Jest手动模拟Giphy API调用的问题

咱们一步步拆解你遇到的问题,先理清楚错误根源,再逐个解决:

错误原因分析

你碰到的TypeError: GifContainer.api is not a function主要有三个核心问题:

  1. 测试文件的调用逻辑错误:displayGifs是GifListContainer类的实例方法,不是直接导出的独立函数,你不能直接通过GifContainer.displayGifs调用它。
  2. 模拟文件的导出不匹配:原api.js用的是命名导出gifApi,但你的模拟文件导出的是default,Jest无法匹配到对应的模拟函数。
  3. 模拟返回的结构不符合真实fetch的规范:原代码里调用了res.json(),但你的模拟直接返回了{ entity: ... },没有模拟fetch响应的json()方法。

解决方案步骤

1. 修正测试文件(GifContainer.test.js)

首先调整测试逻辑,正确实例化组件并调用方法,同时确保jest.mock的位置正确(必须在导入组件之前):

import React from 'react';
// 先让Jest加载模拟的api模块,这行必须放在组件导入之前
jest.mock('./api.js');
// 导入组件类
import GifListContainer from './GifListContainer';

it('should load gifs and update state', async () => {
  // 创建组件实例
  const componentInstance = new GifListContainer();
  // 调用displayGifs方法,用async/await处理异步
  await componentInstance.displayGifs('sunshine');
  
  // 断言state是否正确更新(根据你的mock数据,应该有1个gif的url)
  expect(componentInstance.state.gifs).toHaveLength(1);
  expect(componentInstance.state.gifs[0]).toBeDefined();
});

2. 编写正确的手动模拟文件(mocks/api.js)

确保模拟文件的导出和原api.js一致,同时模拟fetch响应的结构:

import fs from 'fs';
import path from 'path';

// 和原api.js保持一致的命名导出
export const gifApi = (query) => {
  return new Promise((resolve, reject) => {
    // 用path.resolve避免相对路径出错,确保能找到mock数据文件
    const mockFilePath = path.resolve(__dirname, '../__mockData__', `${query}.json`);
    
    fs.readFile(mockFilePath, 'utf8', (err, rawData) => {
      if (err) {
        reject(err);
        return;
      }
      // 模拟fetch返回的Response对象,必须包含json()方法
      resolve({
        json: () => Promise.resolve(JSON.parse(rawData))
      });
    });
  });
};

3. 修正Mock数据格式

你的sunshine.json里有语法错误("type": "gif",后面多了逗号),修正后如下:

{
  "data": [
    {
      "type": "gif",
      "images": {
        "original": {
          "url": "https://example.com/test-gif.gif?param=123"
        }
      }
    }
  ],
  "meta": {
    "status": 200,
    "msg": "OK",
    "response_id": "5b11716a33554c732e0ddf42"
  }
}

可选简化方案(无需读取文件)

如果只是学习手动模拟,不想处理文件读取的问题,可以直接在模拟里返回固定假数据,更简单:

export const gifApi = (query) => {
  return Promise.resolve({
    json: () => Promise.resolve({
      data: [
        {
          type: "gif",
          images: {
            original: {
              url: "https://example.com/gif1.gif?param=1"
            }
          }
        },
        {
          type: "gif",
          images: {
            original: {
              url: "https://example.com/gif2.gif?param=2"
            }
          }
        }
      ],
      meta: {
        status: 200,
        msg: "OK"
      }
    })
  });
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 09:08:41