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

如何在Jasmine中对依赖远程主机数据的函数进行无实际Fetch请求的测试

如何在Jasmine中对依赖远程主机数据的函数进行无实际Fetch请求的测试

我来帮你拆解这个问题,其实在Jasmine里模拟fetch请求、测试依赖远程数据的函数并不复杂,咱们一步步来解决:

一、先模拟全局fetch,避免实际发起网络请求

因为你的loadProducts依赖浏览器的全局fetch函数,所以第一步要在Jasmine里mock这个函数,让它返回咱们预设的测试数据,而不是真的去请求远程主机。

你可以用Jasmine的spyOn方法来监听全局fetch,并让它返回一个模拟的响应:

describe('Product-related functions', () => {
  // 在每个测试前mock fetch
  beforeEach(() => {
    // 定义模拟的远程返回数据
    const mockProductData = [
      {
        id: 1,
        image: 'test.jpg',
        name: 'Test Product',
        rating: { stars: 4.5 },
        priceCents: 999,
        keywords: ['electronics']
      },
      {
        id: 2,
        image: 'appliance.jpg',
        name: 'Test Appliance',
        rating: { stars: 4 },
        priceCents: 1999,
        keywords: ['appliances']
      },
      {
        id: 3,
        image: 'shirt.jpg',
        name: 'Test Shirt',
        rating: { stars: 3.5 },
        priceCents: 499,
        type: 'clothing'
      }
    ];

    // mock fetch,让它返回一个resolved的Promise,模拟成功响应
    spyOn(window, 'fetch').and.returnValue(
      Promise.resolve({
        json: () => Promise.resolve(mockProductData)
      })
    );
  });
});

二、测试getProduct函数

getProduct依赖全局的products数组,所以咱们可以先通过调用loadProducts(此时fetch已经被mock,会用预设数据填充products),然后测试不同场景:

it('should return the correct product when given a valid productId', async () => {
  // 先调用loadProducts填充products数组
  await loadProducts();
  
  const foundProduct = getProduct(2);
  expect(foundProduct.id).toBe(2);
  expect(foundProduct.name).toBe('Test Appliance');
  // 还可以断言它是Appliance类的实例
  expect(foundProduct instanceof Appliance).toBe(true);
});

it('should return undefined when given an invalid productId', async () => {
  await loadProducts();
  
  const foundProduct = getProduct(999);
  expect(foundProduct).toBeUndefined();
});

如果不想依赖loadProducts,也可以直接手动给products数组赋值测试数据,这样更直接:

it('should return correct product with manual test data', () => {
  // 手动设置products数组
  products = [new Product({ id: 5, name: 'Manual Test Product' })];
  
  const foundProduct = getProduct(5);
  expect(foundProduct.name).toBe('Manual Test Product');
});

三、测试loadProducts的请求和数据转换逻辑

除了测试getProduct,你还可以验证loadProducts是否正确发起请求、处理响应:

1. 验证fetch调用了正确的URL

it('should call fetch with the correct URL', async () => {
  const expectedUrl = 'link to host'; // 这里填你代码里实际的请求地址
  await loadProducts();
  
  expect(window.fetch).toHaveBeenCalledWith(expectedUrl);
});

2. 验证返回的数据被正确转换成对应的类实例

it('should transform raw data into correct class instances', async () => {
  await loadProducts();
  
  // 第一个数据是普通Product
  expect(products[0] instanceof Product).toBe(true);
  // 第二个数据包含appliances关键词,应该是Appliance实例
  expect(products[1] instanceof Appliance).toBe(true);
  // 第三个数据type是clothing,应该是Clothing实例
  expect(products[2] instanceof Clothing).toBe(true);
});

3. 测试错误处理逻辑

你还可以模拟fetch失败的情况,验证错误是否被正确捕获:

it('should handle fetch errors properly', async () => {
  // 模拟fetch返回rejected的Promise
  spyOn(window, 'fetch').and.returnValue(Promise.reject(new Error('Network error')));
  // 监听console.error,验证错误信息被输出
  spyOn(console, 'error');
  
  await loadProducts();
  
  expect(console.error).toHaveBeenCalledWith('Network error');
});

小提示

  • 每次测试后最好重置products数组,避免测试之间的干扰,可以在afterEach里重置:
afterEach(() => {
  products = [];
});
  • 如果你的代码是在Node.js环境下(而非浏览器),需要mockglobal.fetch而不是window.fetch。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 08:10:31