在 Typescript 的函数中模拟获取

Mock fetch within a function in Typescript

我是打字稿的新手,如果这是微不足道的,请提前致歉。 我有一个像这样在内部使用 Fetch 的函数

export class MyClass {
  classVar1: string;
  classVar2: string;
...
  async postEvent(event: eventSchema) {
    
    const headers = {
      'Content-type': 'application/json',
      'Api-Key': 'APIKEY}',
    };

    let result = null;

    const response = await fetch('url', {
        method: 'POST',
        body: event,
        headers: headers,
      });
    result = await response;
    
    return result;
  }
}

我正在尝试测试 postEvent 方法,为此我试图仅模拟获取部分。 但无论我如何处理,实际的方法仍然是被调用的方法。 根据我在网上找到的内容,这就是我的 .spec.ts 文件

中的内容
import { MyClass } from './my-class';
import fetch from 'node-fetch';

jest.mock('node-fetch');
describe('My class mocked fetch', () => {
  beforeEach(() => {
    (MyClass as any).postEvent = jest.fn();
    (fetch as any) = jest.fn().mockResolvedValue({
      url: 'url',
      status: 200,
      statusText: 'OK',
      counter: 0,
    });
  });

  it('Calls mockedFetch and gets the mocked values', async () => {
    expect(fetch).toHaveBeenCalledTimes(0);
    const response = await myClass.postEvent('testMsg')
    console.log('RESPONSE', response)
  });

在最后一行 (console.log('RESPONSE', response)),我希望看到 mockResolved 值,即

url: 'url',
  status: 200,
  statusText: 'OK',
  counter: 0,

但它 returns 无论实际提取将生成什么。

有人可以帮忙吗?

p.s 我也阅读了有关 spyOn 方法的信息,但我无法找到适合我上述用例的打字稿示例。 有一个这样的 JS 例子

const fetchMock = jest.spyOn(global, 'fetch').mockImplementation(() => Promise.resolve({ json: () => Promise.resolve([]) }))

但是如果像下面这样在类型脚本中使用它会抛出异常

'Promise<{ json: () => Promise<any[]>; }>' is not assignable to type 'Promise<Response>'.

你的测试有一些问题,我会一一解释。

您想测试 MyClasspostEvent 方法,那么您应该 而不是 将其替换为 jest.fn() 创建的模拟函数.

如果 fetch 函数来自 node-fetch,那么您应该模拟 node-fetch 模块而不是 global.fetch

在我们使用 jest.mock('node-fetch') 模拟 node-fetch 之后,jest 会自动为 node-fetch 公开的每个成员创建模拟对象。

node-fetch 导出 Response class,我们可以用它来创建模拟响应。但是前面说过,jest.mock()已经创建了Responseclass的mocked版本,我们如何得到原来的Responseclass?

jest.requireActual(moduleName) 可以帮助我们,它 returns 实际模块而不是模拟。

综上所述,完整的测试代码如下:

my-class.ts:

import fetch from 'node-fetch';

export class MyClass {
  async postEvent(event) {
    const headers = {
      'Content-type': 'application/json',
      'Api-Key': 'APIKEY',
    };

    const response = await fetch('url', {
      method: 'POST',
      body: event,
      headers: headers,
    });
    return response.json();
  }
}

index.test.ts:

import { MyClass } from './my-class';
import fetch from 'node-fetch';

jest.mock('node-fetch');
const { Response } = jest.requireActual('node-fetch');

describe('69579937', () => {
  it('Calls mockedFetch and gets the mocked values', async () => {
    expect(fetch).toHaveBeenCalledTimes(0);

    (fetch as jest.MockedFunction<typeof fetch>).mockResolvedValue(
      new Response(JSON.stringify({ name: 'teresa teng' }), { url: 'url', status: 200, statusText: 'OK' })
    );
    const myclass = new MyClass();
    const response = await myclass.postEvent('testMsg');
    expect(response).toEqual({ name: 'teresa teng' });
  });
});

测试结果:

 PASS  examples/69579937/my-class.test.ts
  69579937
    ✓ Calls mockedFetch and gets the mocked values (3 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.893 s, estimated 11 s
Ran all test suites related to changed files.