Spies and mocking with Jest
Besides asserting the output of the function call, unit testing includes the usage of spies and mocking. Spies are functions that let you spy on the behavior of functions called indirectly by some other code. Spy can be created by using jest.fn(). Mocking injects test values into the code during the tests. Some of the use cases will be presented below.
- Async function and its resolved value can be mocked using 
mockResolvedValue. Another way to mock it is by usingmockImplementationand providing a function as an argument. 
const calculationService = {calculate: jest.fn()};jest.spyOn(calculationService, 'calculate').mockResolvedValue(value);jest.spyOn(calculationService, 'calculate').mockImplementation(async (a) => Promise.resolve(a));
- Rejected async function can be mocked using 
mockRejectedValueandmockImplementation. 
jest.spyOn(calculationService, 'calculate').mockRejectedValue(new Error(errorMessage));jest.spyOn(calculationService, 'calculate').mockImplementation(async () => Promise.reject(new Error(errorMessage)));await expect(calculateSomething(calculationService)).rejects.toThrowError(Error);
- Sync function and its return value can be mocked using 
mockReturnValueandmockImplementation. 
jest.spyOn(calculationService, 'calculate').mockReturnValue(value);jest.spyOn(calculationService, 'calculate').mockImplementation((a) => a);
- Chained methods can be mocked using 
mockReturnThis. 
// calculationService.get().calculate();jest.spyOn(calculationService, 'get').mockReturnThis();
- Async and sync functions called multiple times can be mocked with different values using 
mockResolvedValueOnceandmockReturnValueOnce, respectively, andmockImplementationOnce. 
jest.spyOn(calculationService, 'calculate').mockResolvedValueOnce(value).mockResolvedValueOnce(otherValue);jest.spyOn(calculationService, 'calculate').mockReturnValueOnce(value).mockReturnValueOnce(otherValue);jest.spyOn(calculationService, 'calculate').mockImplementationOnce((a) => a + 3).mockImplementationOnce((a) => a + 5);
- External modules can be mocked similarly to spies. For the following example, let's suppose 
axiospackage is already used in one function. The following example represents a test file whereaxiosis mocked usingjest.mock(). 
import axios from 'axios';jest.mock('axios');// within test caseaxios.get.mockResolvedValue(data);
- Manual mocks are resolved by writing corresponding modules in 
__mocks__directory, e.g.,fs/promisesmock will be stored in__mocks__/fs/promises.jsfile.fs/promisesmock will be resolved usingjest.mock()in the test file. 
jest.mock('fs/promises');
- To assert called arguments for a mocked function, an assertion can be done using 
toHaveBeenCalledWithmatcher. 
const spy = jest.spyOn(calculationService, 'calculate');expect(spy).toHaveBeenCalledWith(firstArgument, secondArgument);
- To assert skipped call for a mocked function, an assertion can be done using 
not.toHaveBeenCalledmatcher. 
const spy = jest.spyOn(calculationService, 'calculate');expect(spy).not.toHaveBeenCalled();
- To assert how many times mocked function is called, an assertion can be done using 
toHaveBeenCalledTimesmatcher. 
const spy = jest.spyOn(calculationService, 'calculate');calculationService.calculate(3);calculationService.calculate(2);expect(spy).toHaveBeenCalledTimes(2);
- To assert called arguments for the exact call when a mocked function is called multiple times, an assertion can be done using 
toHaveBeenNthCalledWithmatcher. 
const argumentsList = [0, 1];argumentsList.forEach((argument, index) => {expect(calculationService.calculate).toHaveBeenNthCalledWith(index + 1,argument);});
- Methods should be restored to their initial implementation before each test case.
 
// package.json"jest": {// ..."restoreMocks": true}// ...