【问题标题】:Mock fetch within a function in Typescript在 Typescript 的函数中模拟获取
【发布时间】:2021-12-03 09:01:27
【问题描述】:

我是打字稿的新手,如果这是微不足道的,请提前道歉。 我有一个像这样在内部使用 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 方法,为此我正在尝试仅模拟 fetch 部分。 但无论我如何处理这个问题,实际方法仍然是被调用的方法。 根据我在网上找到的内容,这就是我的 .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,

但它会返回实际 fetch 会生成的任何内容。

有人可以帮忙吗?

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>'.

【问题讨论】:

    标签: typescript jestjs mocking fetch


    【解决方案1】:

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

    你想测试MyClasspostEvent方法,那么你应该jest.fn()创建的模拟函数替换它。

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

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

    node-fetch 导出Response 类,我们可以使用它来创建模拟响应。但是如前所述,jest.mock() 已经创建了 Response 类的模拟版本,我们如何获得原始的 Response 类?

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

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

    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.
    

    【讨论】:

      猜你喜欢
      • 2020-11-12
      • 1970-01-01
      • 1970-01-01
      • 2023-03-26
      • 2020-06-06
      • 1970-01-01
      • 2022-07-22
      • 2015-09-16
      • 2018-06-04
      相关资源
      最近更新 更多