Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript and Jest: Avoiding type errors on mocked functions

When wanting to mock external modules with Jest, we can use the jest.mock() method to auto-mock functions on a module.

We can then manipulate and interrogate the mocked functions on our mocked module as we wish.

For example, consider the following contrived example for mocking the axios module:

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); }); 

The above will run fine in Jest but will throw a Typescript error:

Property 'mockReturnValueOnce' does not exist on type '(url: string, config?: AxiosRequestConfig | undefined) => AxiosPromise'.

The typedef for axios.get rightly doesn't include a mockReturnValueOnce property. We can force Typescript to treat axios.get as an Object literal by wrapping it as Object(axios.get), but:

What is the idiomatic way to mock functions while maintaining type safety?

like image 334
duncanhall Avatar asked Jul 24 '18 09:07

duncanhall


People also ask

Does Jest clear mocks?

Jest mockReset/resetAllMocks vs mockClear/clearAllMocksmockClear() does, and also removes any mocked return values or implementations. This is useful when you want to completely reset a mock back to its initial state. (Note that resetting a spy will result in a function with no return value).

What is __ mocks __ in Jest?

Mocking Node modules​ If the module you are mocking is a Node module (e.g.: lodash ), the mock should be placed in the __mocks__ directory adjacent to node_modules (unless you configured roots to point to a folder other than the project root) and will be automatically mocked. There's no need to explicitly call jest.

Does Jest spyOn mock?

Before every function is run in the file, jest will mock , and after every , jest will restore the function to its original implementation. Using the hooks for setup ensures that every test is fresh and independent of each other.

How does Jest mocking work?

Mock functions allow you to test the links between code by erasing the actual implementation of a function, capturing calls to the function (and the parameters passed in those calls), capturing instances of constructor functions when instantiated with new , and allowing test-time configuration of return values.


1 Answers

Add this line of code const mockedAxios = axios as jest.Mocked<typeof axios>. And then use the mockedAxios to call the mockReturnValueOnce. With your code, should be done like this:

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); }); 
like image 113
hutabalian Avatar answered Sep 30 '22 21:09

hutabalian