Search code examples
reactjsjestjsaxios-mock-adapter

How to resolve axios mocking errors using JEST and REACT


Have created unit test cases using axios mock approach and do see below console errors. Have tried many approaches but none resolved the problem. Very new to REACT/JEST community, but trying best to resolve this.

Expectation:

  1. All test cases including success, error scenarios should be 100% covered and should pass with no warnings/errors.
  2. Response should be tested with empty results list and as well with non-empty results list.
  3. Error scenarios due to timeout/network should also be handled.

Errors:


Expected: undefined
Received: {"results": []}

(node:76675) UnhandledPromiseRejectionWarning: 
Unhandled promise rejection. This error originated 
either by throwing inside of an async function without a catch block, 
or by rejecting a promise which was not handled with .catch(). 
(rejection id: 1)

(node:76675) [DEP0018] DeprecationWarning: Unhandled promise rejections 
are deprecated. In the future, promise rejections that are not handled will 
terminate the Node.js process with a non-zero exit code.

What I tried:

index.js

export default getAreas = area => axios.get(`/test/areas/${area}`);

__mocks__/axios.js

const axiosMocked = {
  get: jest.fn(() => Promise.resolve({ results: [] }))
};
export default axiosMocked;

__tests__/index.test.js

import mockAxios from 'axios';
import getAreas from '../index';

afterEach(() => {
  jest.clearAllMocks();
});

it('fetches results from api', () => {
  mockAxios.get.mockImplementationOnce(() => Promise.resolve({ results: [] }));
  getAreas('atl').then(response => {
    expect(response).toEqual();
  });
  expect(mockAxios.get).toHaveBeenCalledTimes(1);
  expect(mockAxios.get).toHaveBeenCalledWith('/test/areas/atl');
});

Solution

  • Here is a solution using jest.mock method to mock axios manually without using any third-party mock library.

    index.ts:

    import axios from 'axios';
    
    const getAreas = area => axios.get(`/test/areas/${area}`);
    
    export default getAreas;
    

    index.spec.ts:

    import getAreas from './';
    import axios from 'axios';
    
    jest.mock('axios');
    
    afterEach(() => {
      jest.clearAllMocks();
    });
    
    describe('getAreas', () => {
      it('fetches results from api', () => {
        (axios.get as jest.Mock).mockResolvedValueOnce({ results: [] });
        getAreas('atl').then(response => {
          expect(response).toEqual({ results: [] });
        });
        expect(axios.get).toHaveBeenCalledTimes(1);
        expect(axios.get).toHaveBeenCalledWith('/test/areas/atl');
      });
    });
    

    Unit test result with 100% coverage:

     PASS  src/stackoverflow/58357043/index.spec.ts (7.557s)
      getAreas
        ✓ fetches results from api (9ms)
    
    ----------|----------|----------|----------|----------|-------------------|
    File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
    ----------|----------|----------|----------|----------|-------------------|
    All files |      100 |      100 |      100 |      100 |                   |
     index.ts |      100 |      100 |      100 |      100 |                   |
    ----------|----------|----------|----------|----------|-------------------|
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        8.952s
    

    Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/58357043