代码之家  ›  专栏  ›  技术社区  ›  duncanhall

typescript和jest:避免模拟函数上的类型错误

  •  6
  • duncanhall  · 技术社区  · 6 年前

    当想要用jest模拟外部模块时,我们可以使用 jest.mock() 方法在模块上自动模拟函数。

    然后,我们可以按照自己的意愿在模拟模块上操纵和询问模拟函数。

    例如,考虑以下模拟AXIOS模块的人为示例:

    import myModuleThatCallsAxios from '../myModule';
    import axios from 'axios';
    
    jest.mock('axios');
    
    it('Calls the GET method as expected', async () => {
      const expectedResult: string = 'result';
    
      axios.get.mockReturnValueOnce({ data: expectedResult });
      const result = await myModuleThatCallsAxios.makeGetRequest();
    
      expect(axios.get).toHaveBeenCalled();
      expect(result).toBe(expectedResult);
    });
    

    上面的代码会很好地运行,但会抛出一个typescript错误:

    类型“”(url: 字符串,配置?:axiosrequestconfig未定义)=>axiospromise'。

    TyPulf用于 axios.get 正确的不包括 mockReturnValueOnce 财产。我们可以强制处理typescript AXIO.GET 作为对象文本包装为 Object(axios.get) 但是,

    在维护类型安全的同时模拟函数的惯用方法是什么?

    3 回复  |  直到 5 年前
        1
  •  10
  •   hutabalian    6 年前

    添加此行代码 const mockedAxios = axios as jest.Mocked<typeof axios> 。然后使用mockedaxios调用mockReturnValueOnce。 对于您的代码,应该这样做:

    import myModuleThatCallsAxios from '../myModule';
    import axios from 'axios';
    
    jest.mock('axios');
    const mockedAxios = axios as jest.Mocked<typeof axios>;
    
    it('Calls the GET method as expected', async () => {
      const expectedResult: string = 'result';
    
      mockedAxios.get.mockReturnValueOnce({ data: expectedResult });
      const result = await myModuleThatCallsAxios.makeGetRequest();
    
      expect(mockedAxios.get).toHaveBeenCalled();
      expect(result).toBe(expectedResult);
    });
    
        2
  •  9
  •   Brian Adams    6 年前

    在保持类型安全使用的同时,以惯用方式模拟函数 spyOn mockReturnValueOnce :

    import myModuleThatCallsAxios from '../myModule';
    import axios from 'axios';
    
    it('Calls the GET method as expected', async () => {
      const expectedResult: string = 'result';
    
      // set up mock for axios.get
      const mock = jest.spyOn(axios, 'get');
      mock.mockReturnValueOnce({ data: expectedResult });
    
      const result = await myModuleThatCallsAxios.makeGetRequest();
    
      expect(mock).toHaveBeenCalled();
      expect(result).toBe(expectedResult);
    
      // restore axios.get
      mock.mockRestore();
    });
    
        3
  •  4
  •   Estus Flask    6 年前

    为导入提供新功能以扩展原始模块的常用方法 declare module "axios" { ... } 。这不是最好的选择,因为这应该对整个模块进行,而模拟可能在一个测试中可用,在另一个测试中不可用。

    在这种情况下,类型安全方法是在需要时断言类型:

      (axios.get as jest.Mock).mockReturnValueOnce({ data: expectedResult });
      ...
      expect(axios.get as jest.Mock).toHaveBeenCalled();