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?
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).
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.
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.
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.
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); });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With