Search code examples
typescriptaxiosts-jest

How to resolve "TypeError: mockedAxios.get.mockResolvedValue is not a function" error?


I am using Jest for my TypeScript project. I am trying to mock Axios but keep getting TypeError: mockedAxios.get.mockResolvedValue is not a function error. I have tried several ways as below but I'm not sure what am I doing wrong here.

I saw some similar articles on this website but when I tried this on my side, I was unable to resolve it.

References:

Code:

httpRequest.service.ts

import { injectable } from 'inversify';
import axios from 'axios';

@injectable()
export default class HttpService {
  /**
     * Generic function to make HTTP calls.
     * @template T
     * @param [options]
     * @returns request
     */
  public async request<T>(options: object = {}): Promise<T> {
    return axios.request(options)
      .then((response) => response.data)
      .catch((error) => {
        throw error;
      });
  }
}

httpRequest.service.spec.ts

Option-1 = using AxiosResponse from axios

import 'reflect-metadata';
import HttpService from '../httpRequest.service';
import axios, { AxiosResponse } from 'axios';

describe('httpService', () => {
  let httpService: HttpService;
  let mockedAxios: any;

  beforeEach(() => {
    jest.resetModules();
    jest.resetAllMocks();
    jest.mock('axios');

    mockedAxios = axios as jest.Mocked<typeof axios>;

    httpService = new HttpService();
  });

  describe('request', () => {
    it('successfully returns response', async () => {

      const axiosResponse: AxiosResponse = {
        data: {
          userId: 1,
          id: 1,
          title: 'mock title',
          body: 'mock body',
        },
        status: 200,
        statusText: 'OK',
        config: {},
        headers: {},
      };

      //Mocking axios function rather than a method
      mockedAxios.get.mockResolvedValue(axiosResponse);

      //Act
      const result = await httpService.request();

      //Assert
      expect(result).toBe({
        userId: 1,
        id: 1,
        title: 'mock title',
        body: 'mock body',
      });

    });

  });
});

Option-2 = using mocked from ts-jest

import 'reflect-metadata';
import HttpService from '../httpRequest.service';
import axios, { AxiosResponse } from 'axios';
import { mocked } from 'ts-jest/dist/utils/testing';

describe('httpService', () => {
  let httpService: HttpService;

  beforeEach(() => {
    jest.resetModules();
    jest.resetAllMocks();
    jest.mock('axios');

    httpService = new HttpService();
  });

  describe('request', () => {
    it('successfully returns response', async () => {

      const axiosResponse: AxiosResponse = {
        data: {
          userId: 1,
          id: 1,
          title: 'mock title',
          body: 'mock body',
        },
        status: 200,
        statusText: 'OK',
        config: {},
        headers: {},
      };

      //Mocking axios function rather than a method
      mocked(axios).mockResolvedValue(axiosResponse);
      // mocked.get.mockResolvedValue(axiosResponse);

      //Act
      const result = await httpService.request();

      //Assert
      expect(result).toBe({
        userId: 1,
        id: 1,
        title: 'mock title',
        body: 'mock body',
      });

    });

  });
});

Option-3 = using AxiosStatic from axios

import HttpService from '../httpRequest.service';
import axios, { AxiosStatic } from 'axios';

interface AxiosMock extends AxiosStatic {
  mockResolvedValue: any
  mockRejectedValue: any
}

describe('httpService', () => {
  let httpService: HttpService;
  let mockAxios: any;

  beforeEach(() => {
    jest.resetModules();
    jest.resetAllMocks();
    jest.mock('axios');

    mockAxios = axios as AxiosMock;
    httpService = new HttpService();
  });

  describe('request', () => {
    it('successfully returns response', async () => {

      const axiosResponse: AxiosResponse = {
        data: {
          userId: 1,
          id: 1,
          title: 'mock title',
          body: 'mock body',
        },
        status: 200,
        statusText: 'OK',
        config: {},
        headers: {},
      };

      //Mocking axios function rather than a method
      mockAxios.mockResolvedValue(axiosResponse);

      //Act
      const result = await httpService.request();

      //Assert
      expect(result).toBe({
        userId: 1,
        id: 1,
        title: 'mock title',
        body: 'mock body',
      });

    });

  });
});

Solution

  • I was able to resolve this by making 2 changes in my Option-1 solution:

    1. Move jest.mock('axios'); after import statement. I am not sure why it is not working when I declare it inside beforeAll (looking into this).
    2. Change mockedAxios.get.mockResolvedValue(axiosResponse); to mockedAxios.request.mockResolvedValue(axiosResponse);. This is a silly mistake where my function uses .request but I was mocking .get.

    Here is full solution.

    import 'reflect-metadata';
    import HttpService from '../httpRequest.service';
    import axios, { AxiosResponse } from 'axios';
    jest.mock('axios');
    
    describe('httpRequest', () => {
      let httpService: HttpService;
      let mockedAxios: any;
    
      beforeAll(() => {
        jest.resetModules();
        jest.resetAllMocks();
    
        mockedAxios = axios as jest.Mocked<typeof axios>;
        httpService = new HttpService();
    
      });
    
      describe('request', () => {
        it('successful', async () => {
    
          const mockAxiosData = {
            userId: 1,
            id: 1,
            title: '',
            body: '',
          };
    
          const axiosResponse: AxiosResponse = {
            data: mockAxiosData,
            status: 200,
            statusText: 'OK',
            config: {},
            headers: {},
          };
    
          mockedAxios.request.mockResolvedValue(axiosResponse);
    
          const request = await httpService.request();
          expect(request).toBe(mockAxiosData);
    
        });
      });
    
    });