Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to test axios interceptors with jest

In my project, I have a namespace that exports some functions that use Axios, in the same file I add an interceptor to axios instance like that :

axios.interceptors.response.use(
    (res) => res,
    (error) => {
      if (
        error.response &&
        (error.response.status?.toString() === "400" ||
          error.response.status?.toString() === "403" ||
          error.response.status?.toString() === "404")
      ) {
        return Promise.reject(
          Error(JSON.stringify(error.response.data?.status?.errors[0]))
        );
      } else if (error.response) {
        return Promise.reject(
          Error(
            `server responsed with the following code: ${error.response?.status} and the following message: ${error.response?.statusText}`
          )
        );
      } else if (error.request) {
        return Promise.reject(
          Error(
            "The request was made but no response was received, check your network connection"
          )
        );
      } else Promise.reject(error);
    }
);

I want to test that this interceptor works as expected, I search the forms here and googled a lot but all the answers are basically mocking the interceptor not testing it.

I have tried:

  1. mocking the response of an axios post request and checking the AxiosPromise that gets returned but it only contained the result I mocked. it seems that it ignores the interceptor when I mock using mockResolvedValue.
  2. I have tried adding an interceptor to the mocked axios instance but that did not work too.

Thanks

like image 986
Islam Rostom Avatar asked Dec 19 '25 19:12

Islam Rostom


2 Answers

What about pulling the function out and testing it without axios?

import axios, { AxiosError, AxiosResponse } from 'axios'

export const onFulfilled = (response: AxiosResponse) => {
  // Your interceptor handling a successful response
}
export const onRejected = (error: AxiosError) => {
  // Your interceptor handling a failed response
}

axios.interceptors.response.use(onFulfilled, onRejected)

Now you can test the functions onFullfilled and onRejected with less dependencies to axios.

like image 63
ueznem Avatar answered Dec 21 '25 09:12

ueznem


You have to mock the interceptor and run the callbacks.

Here is an example on how to do it:

httpService.ts

import axios from "axios";
import { toast } from "react-toastify";

axios.interceptors.request.use((config) => {
  config.baseURL = process.env.API_URL || "http://localhost:5000";
  return config;
});

axios.interceptors.response.use(null, (error) => {
  const expectedError =
    error.response &&
    error.response.status >= 400 &&
    error.response.status < 500;

  if (!expectedError) {
    toast.error("An unexpected error occured");
  }

  return Promise.reject(error);
});

export default {
  get: axios.get,
  post: axios.post,
  put: axios.put,
  delete: axios.delete,
};

httpService.test.ts

import axios from "axios";
import { toast } from "react-toastify";
import "./httpService";

jest.mock("axios", () => ({
  __esModule: true,
  default: {
    interceptors: {
      request: { use: jest.fn(() => {}) },
      response: { use: jest.fn(() => {}) },
    },
  },
}));

const fakeError = {
  response: {
    status: undefined,
  },
};

const mockRequestCallback = (axios.interceptors.request.use as jest.Mock).mock
  .calls[0][0];
const mockResponseErrorCallback = (axios.interceptors.response.use as jest.Mock)
  .mock.calls[0][1];
const toastErrorSpy = jest.spyOn(toast, "error");

beforeEach(() => {
  toastErrorSpy.mockClear();
});

test("request error interceptor", () => {
  expect(mockRequestCallback({})).toStrictEqual({
    baseURL: "http://localhost:5000",
  });
});

test("unexpected error on response interceptor", () => {
  fakeError.response.status = 500;

  mockResponseErrorCallback(fakeError).catch(() => {});
  expect(toastErrorSpy).toHaveBeenCalled();
});

test("expected error on response interceptor", () => {
  fakeError.response.status = 400;

  mockResponseErrorCallback(fakeError).catch(() => {});
  expect(toastErrorSpy).not.toHaveBeenCalled();
});

like image 29
lueenavarro Avatar answered Dec 21 '25 08:12

lueenavarro



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!