如何测试从后端获取的 React 服务

How can I test a React Service that fetchs from a backend

我正在检查测试覆盖率,但我目前没有通过 fetch 行(第 3 行)。如何测试获取功能?

服务:

export const taskManagerRemoteService = {
  getTasks: (): Promise<any> => {
    return fetch(`${process.env.REACT_APP_BACKEND_URL}${process.env.REACT_APP_TASKS_URI}`, {
      method: "GET",
      headers:{
        'Content-Type': 'application/json'
      }
    })
  }
}

测试:

import "@testing-library/react"
import { taskManagerRemoteService } from "./task-manager.remote.service";

describe("TaskManagerRemoteService", () => {
  afterAll(() => {
    jest.clearAllMocks()
  })

  it('should get tasks when getTasks method is called', async () => {
    const spy = jest.spyOn(taskManagerRemoteService, 'getTasks').mockImplementation(() => Promise.resolve([{}]))
    const tasks = await taskManagerRemoteService.getTasks();

    expect(spy).toHaveBeenCalled()
    expect(tasks).toStrictEqual([{}])
  
    spy.mockReset();
    spy.mockRestore();
  })
})

非常感谢您

你正在测试 taskManagerRemoteService.getTasks 方法,所以你不应该模拟它。您应该模拟 fetch 函数及其 resolved/rejected 值。

有两种方法可以模拟 API 请求:

  1. msw - 通过拦截网络级别的请求进行模拟。这样你就必须安装额外的包并进行设置。不需要mock,使用原始的fetch方式,更接近真实的运行环境

  2. global.fetch = jest.fn() - 只需模拟 fetch 函数,不需要安装任何包。但潜在的风险是不正确的模拟改变了 fetch 的行为,测试通过,实际代码失败。

下面是使用第二种方式的代码:

task-manager.remote.service.ts:

export const taskManagerRemoteService = {
  getTasks: (): Promise<any> => {
    return fetch(`${process.env.REACT_APP_BACKEND_URL}${process.env.REACT_APP_TASKS_URI}`, {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
      },
    });
  },
};

task-manager.remote.service.test.ts:

import '@testing-library/react';
import { taskManagerRemoteService } from './task-manager.remote.service';

describe('TaskManagerRemoteService', () => {
  let oFetch: typeof global.fetch;
  beforeAll(() => {
    oFetch = global.fetch;
  });
  afterAll(() => {
    global.fetch = oFetch;
  });
  it('should get tasks when getTasks method is called', async () => {
    global.fetch = jest.fn().mockResolvedValue([{}]);
    const tasks = await taskManagerRemoteService.getTasks();

    expect(global.fetch).toHaveBeenCalled();
    expect(tasks).toStrictEqual([{}]);
  });
});

测试结果:

 PASS  Whosebug/71400354/task-manager.remote.service.test.ts
  TaskManagerRemoteService
    ✓ should get tasks when getTasks method is called (5 ms)

--------------------------------|---------|----------|---------|---------|-------------------
File                            | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
--------------------------------|---------|----------|---------|---------|-------------------
All files                       |     100 |      100 |     100 |     100 |                   
 task-manager.remote.service.ts |     100 |      100 |     100 |     100 |                   
--------------------------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.83 s, estimated 2 s