【问题标题】:jest typescript property mock does not exist on type类型上不存在开玩笑的打字稿属性模拟
【发布时间】:2019-02-26 16:20:40
【问题描述】:

当使用jest.fn() 添加模拟时,您通常可以访问.mock 属性以访问详细信息,例如调用,类似于以下内容:

test('not working', () => {
    const foo = new Foo();
    foo.addListener = jest.fn();
    foo.func(); // will call addListener with a callback
    const callback = foo.addListener.mock.calls[0][0];
    expect(callback()).toEqual(1); // test the callback
});

在 typescript 而不是普通的 javascript 中实现测试时,我得到了错误:

错误 TS2339:类型“(回调:()=>数字)=> void”上不存在属性“模拟”。

我可以通过转换为any 来消除错误,但肯定有更好的方法:

const callback = (foo.addListener as any).mock.calls[0][0];

在这个简单的代码中,可以重写模拟以使用 jest.fn(fn => { callback = fn; }); 存储参数,但使用 foo.addListener.mockClear() 时会发生同样的错误,不能以相同的方式重新编写。

那么我怎样才能摆脱错误,最好不失去类型安全?

【问题讨论】:

    标签: typescript jestjs mocking


    【解决方案1】:

    对于任何来到这里的人来说,比投射到 any 更好一点的可能是投射为 jest.Mock

    const callback = (foo.addListener as jest.Mock).mock.calls[0][0];
    

    2021 年 9 月更新

    要获得一个既满足mocked函数类型又满足jest mock类型jest.MockedFunction的mock函数:

    const addListenerMock = addListener as jest.MockedFunction<typeof addListener>;
    

    【讨论】:

      【解决方案2】:

      使用axios时出现以下错误。

      TS2339 (TS) 属性“mockResolvedValueOnce”在类型上不存在 'AxiosStatic'

      尝试使用axios as jest.Mock,但出现以下错误:

      TS2352 (TS) 将“AxiosStatic”类型转换为“Mock”类型 可能是一个错误,因为这两种类型都没有与 其他。如果这是故意的,请将表达式转换为“未知” 第一的。类型“AxiosStatic”缺少以下属性 键入“Mock”:getMockName、mock、mockClear、mockReset 和 12 更多。

      通过指定为axios as unknown as jest.Mock解决了它

      AxiosRequest.test.tsx

      import axios from 'axios';
      import { MediaByIdentifier } from '../api/mediaController';
      
      jest.mock('axios', () => jest.fn());
      
      test('Test AxiosRequest',async () => {
          const mRes = { status: 200, data: 'fake data' };
          (axios as unknown as jest.Mock).mockResolvedValueOnce(mRes);
          const mock = await MediaByIdentifier('Test');
          expect(mock).toEqual(mRes);
          expect(axios).toHaveBeenCalledTimes(1);
      });
      

      mediaController.ts:

      import { sendRequest } from './request'
      import { AxiosPromise } from 'axios'
      import { MediaDto } from './../model/typegen/mediaDto';
      
      const path = '/api/media/'
      
      export const MediaByIdentifier = (identifier: string): AxiosPromise<MediaDto> => {
          return sendRequest(path + 'MediaByIdentifier?identifier=' + identifier, 'get');
      }
      

      request.ts:

      import axios, { AxiosPromise, AxiosRequestConfig, Method } from 'axios';
      
      const getConfig = (url: string, method: Method, params?: any, data?: any) => {
           const config: AxiosRequestConfig = {
               url: url,
               method: method,
               responseType: 'json',
               params: params,
               data: data,
               headers: { 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/json' },
          }
          return config;
      }
      
      export const sendRequest = (url: string, method: Method, params?: any, data?: any): AxiosPromise<any> => {
          return axios(getConfig(url, method, params, data))
      }
      

      【讨论】:

        【解决方案3】:

        您可以将jest.spyOnmockImplementation 等函数结合使用来模拟函数,同时在TypeScript 中保持类型安全:

        class Foo {
          addListener = (callback: () => number) => { }
          func = () => {
            this.addListener(() => 1);
          }
        }
        
        test('working', () => {
          const foo = new Foo();
          const mockAddListener = jest.spyOn(foo, 'addListener'); // spy on foo.addListener
          mockAddListener.mockImplementation(() => { }); // replace the implementation if desired
          foo.func(); // will call addListener with a callback
          const callback = mockAddListener.mock.calls[0][0];
          expect(callback()).toEqual(1); // SUCCESS
        });
        

        【讨论】:

        • 有没有办法在类中模拟一个函数而不在测试中启动它?
        猜你喜欢
        • 1970-01-01
        • 2021-01-09
        • 2018-09-16
        • 2019-02-06
        • 2020-01-07
        • 2019-11-08
        • 2020-07-09
        • 2017-03-02
        • 2021-09-07
        相关资源
        最近更新 更多