18

I’m having trouble mocking axios with Jest and react-testing-library. I’m stuck on an error around axios interceptors and can’t make my way around it.

This is my api.js file:

import axios from 'axios';

const api = axios.create({
  baseURL: window.apiPath,
  withCredentials: true,
});

api.interceptors.request.use(config => {
  const newConfig = Object.assign({}, config);
  newConfig.headers.Accept = 'application/json';

  return newConfig;
}, error => Promise.reject(error));

The call to api in my component:

const fetchAsync = async endpoint => {
  const result = await api.get(endpoint);
  setSuffixOptions(result.data.data);
};

Then in my spec file:

jest.mock('axios', () => {
  return {
    create: jest.fn(),
    get: jest.fn(),
    interceptors: {
      request: { use: jest.fn(), eject: jest.fn() },
      response: { use: jest.fn(), eject: jest.fn() },
    },
  };
});

test('fetches and displays data', async () => {
  const { getByText } = render(<Condition {...props} />);
  await expect(getByText(/Current milestone/i)).toBeInTheDocument();
});

The test fails with this message:

    TypeError: Cannot read property 'interceptors' of undefined

       6 | });
       7 |
    >  8 | api.interceptors.request.use(config => {
         |                ^
       9 |   const newConfig = Object.assign({}, config);
      10 |   newConfig.headers.Accept = 'application/json';
      11 |

What am I doing wrong here?

Mohammad Fared
  • 588
  • 1
  • 7
  • 19
Brandon Durham
  • 7,096
  • 13
  • 64
  • 101

2 Answers2

30

the create method is what creates the api which has the get and interceptors methods. So you need to create a dummy api object:


jest.mock('axios', () => {
  return {
    create: jest.fn(() => ({
      get: jest.fn(),
      interceptors: {
        request: { use: jest.fn(), eject: jest.fn() },
        response: { use: jest.fn(), eject: jest.fn() }
      }
    }))
  }
})
cyberwombat
  • 38,105
  • 35
  • 175
  • 251
  • are you sure this will work? I tried it but no luck. I had to do axios module mock to make it work. @cyberwombat – Murali N Nov 05 '21 at 20:48
  • @MuraliPrasanth definitely worked though that was a bit back. Perhaps the internals of axios have changed? – cyberwombat Nov 06 '21 at 22:26
  • 1
    axios might have changed it's internals but this seems a very clean mocking but unfortunately it didn't work for me. – Murali N Nov 07 '21 at 17:47
  • @MuraliPrasanth I looked at axios core and it seems to still use `create`. If you want to make a sandbox I can take a peek. – cyberwombat Nov 08 '21 at 18:37
1

You must mock api.js, not Axios.

    import { FuncToCallAPI } from './funcAPI';
    import api from './api';

    describe('Mock api.ts', () => {
      it('should get data', async () => {
       
        const Expected = { status: 200, data: {} };

        jest.spyOn(api, 'get').mockResolvedValue(Expected);

        const result = await FuncToCallAPI('something');

        expect(result).toEqual(Expected);
  });
});

Then create a test for api.js, mocking the axios.create as you did before.