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

使用Intern对React/JavaScript中HTTP方法(GET、POST)做单元测试

用fetch-mock + Intern expect 测试GET/POST函数的完整指南

别担心,第一次写单元测试摸不清头绪太正常了!我来一步步给你拆解怎么用fetch-mock拦截请求、模拟响应,再用Intern的expect断言验证函数输出。

先搞懂核心逻辑:fetch-mock的作用

fetch-mock的核心就是拦截真实的fetch调用,替换成你预设的模拟响应——这样你完全不用依赖真实API,就能测试你的请求函数逻辑是否正确。

基础步骤:测试前准备与清理

不管测试GET还是POST,都要在测试开始前初始化fetch-mock,测试结束后清理它,避免影响其他测试用例:

import fetchMock from 'fetch-mock';
import { expect } from 'intern/chai';
// 导入你要测试的函数
import { fetchNumbers, submitData } from './your-api-functions';

describe('API Functions', () => {
  beforeEach(() => {
    // 初始化fetch-mock,确保之前的mock被清理
    fetchMock.restore();
  });

  afterEach(() => {
    // 测试结束后恢复真实的fetch,避免污染其他测试
    fetchMock.restore();
  });

  // 接下来写具体的测试用例
});

测试GET函数:验证返回数据是否符合预期

假设你的GET函数fetchNumbers是这样的:

export async function fetchNumbers() {
  const response = await fetch('/api/numbers');
  return response.json();
}

测试用例写法:

it('should fetch numbers correctly from API', async () => {
  // 1. 设置模拟响应:当GET请求到/api/numbers时,返回预设的数组
  const mockResponse = [1, 2, 3, 4];
  fetchMock.get('/api/numbers', {
    body: mockResponse,
    status: 200,
    headers: { 'Content-Type': 'application/json' }
  });

  // 2. 调用你要测试的GET函数
  const result = await fetchNumbers();

  // 3. 用Intern的expect断言:实际返回值和预期值是否一致
  expect(result).to.deep.equal(mockResponse);

  // 额外验证:确保fetch确实被调用了一次,且URL正确
  expect(fetchMock.calls('/api/numbers').length).to.equal(1);
});

关键点:

  • 用fetchMock.get()匹配GET请求,第一个参数是要拦截的URL,第二个参数是模拟的响应体、状态码、头等信息
  • 因为返回的是数组/对象,要用to.deep.equal()做深比较,不能用普通的equal()
  • 可以用fetchMock.calls()验证请求是否被正确触发,避免函数里漏发请求的情况

测试POST函数:验证请求参数与响应处理

假设你的POST函数submitData是这样的:

export async function submitData(data) {
  const response = await fetch('/api/submit', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(data)
  });
  return response.json();
}

测试用例写法:

it('should submit data correctly and return success message', async () => {
  // 1. 设置动态模拟响应:根据POST的请求体返回不同结果
  const testData = { value: 42 };
  const mockSuccessResponse = { success: true, message: 'Data submitted successfully' };
  
  fetchMock.post('/api/submit', (url, options) => {
    // 解析请求体,验证是否和我们传入的一致
    const requestBody = JSON.parse(options.body);
    if (requestBody.value === testData.value) {
      return { body: mockSuccessResponse, status: 200 };
    } else {
      return { body: { error: 'Invalid data' }, status: 400 };
    }
  });

  // 2. 调用POST函数,传入测试数据
  const result = await submitData(testData);

  // 3. 断言返回结果符合预期
  expect(result).to.deep.equal(mockSuccessResponse);

  // 额外验证:请求的method、headers、body是否正确
  const callArgs = fetchMock.lastCall('/api/submit')[1]; // 获取最后一次请求的配置
  expect(callArgs.method).to.equal('POST');
  expect(callArgs.headers['Content-Type']).to.equal('application/json');
  expect(JSON.parse(callArgs.body)).to.deep.equal(testData);
});

// 额外测试错误场景:比如请求参数错误时的处理
it('should handle error response when submitting invalid data', async () => {
  fetchMock.post('/api/submit', {
    body: { error: 'Invalid data' },
    status: 400
  });

  try {
    await submitData({ value: 'invalid' });
    // 如果没抛出错误,测试失败
    expect.fail('Expected an error to be thrown');
  } catch (error) {
    // 断言错误信息符合预期(假设你的函数会处理错误并抛出)
    expect(error.message).to.equal('Invalid data');
  }
});

关键点:

  • 用fetchMock.post()匹配POST请求,第二个参数可以是静态响应,也可以是一个函数,动态处理请求并返回响应
  • 可以通过fetchMock.lastCall()获取请求的详细配置,验证请求的method、headers、body是否符合预期
  • 一定要测试错误场景(比如400、500状态码),确保函数能正确处理异常

模拟响应的进阶技巧

  • 匹配动态URL:如果你的URL有参数(比如/api/numbers?id=123),可以用正则表达式匹配:fetchMock.get(/\/api\/numbers\?id=\d+/, mockResponse)
  • 模拟延迟:可以给响应加delay属性,模拟网络延迟:fetchMock.get('/api/numbers', { body: mockResponse, delay: 1000 })
  • 模拟网络失败:用throws选项模拟fetch抛出错误:fetchMock.get('/api/numbers', { throws: new Error('Network error') })

这样一步步来,你就能完整测试你的GET和POST函数啦!如果还有具体的函数逻辑细节,可以再调整测试用例~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:18:51