1

I started by following the answer in this StackOverflow Question

But I added a helper function I use which creates a new Axios instance with the auth token associated with the user.

Which looks a little like this:

import axios from "axios";
const mockAxios: jest.Mocked<typeof axios> = jest.createMockFromModule("axios");

// this is the key to fix the axios.create() undefined error!
mockAxios.create = jest.fn(() => {
  return mockAxios;
});

export const createAuthenticatedInstance = () => {
  return mockAxios.create();
};
export default mockAxios;

Why does mockAxios.create() return undefined?

While the object 'mockAxios' (and the create function) is defined. When I actually call create it returns undefined despite the function being declared.

I know that I can side-step the issue by just returning mockAxios against but I'd like to understand why it doesn't work in the first place. What I'd expect is to return a new instance, which would be identical to mockAxios but it just returns undefined.

Teneff
  • 30,564
  • 13
  • 72
  • 103
Luis Osta
  • 144
  • 1
  • 13
  • Because it doesn't know what value to return otherwise. The function exists, but in the absence of a value to return the default is undefined. *"What I'd expect is to return a new instance"* - that's what the real module does, but Jest isn't magic. – jonrsharpe Oct 26 '20 at 13:36
  • I don't think I follow why so what's causing the mockAxios.create override to not work? – Luis Osta Oct 26 '20 at 13:41
  • @LuisOsta if I have to guess why it returns `undefined` it would be because you've called `jest.mock` on the file where `createAuthenticatedInstance` is defined, so jest have generated a mock function for `createAuthenticatedInstance`, which by default should return `undefined` – Teneff Oct 26 '20 at 17:07

1 Answers1

2

If you're creating an auto-mock (within __mocks__) it's meant to be a mock of the module and any helper functions are not expected to be within the module, but probably somewhere else with your code

Exmaple:

src/axios.utils.ts (utility module which exports axios and the function)
import axios from "axios";

export const createAuthenticatedInstance = (
  ...args: Parameters<typeof axios.create>
) => {
  return axios.create(...args);
};

export default axios;
src/__mocks__/axios.ts (the axios mock)
const axios: jest.Mocked<typeof import("axios").default> = jest.createMockFromModule(
  "axios"
);

axios.create.mockReturnThis();

export default axios;
src/api.ts (api implementation that uses the axios.util)

import axios from "axios";
import { createAuthenticatedInstance } from "./axios.utils";

const client = createAuthenticatedInstance({
  baseURL: "http://example.com:80/main",
});

export default {
  makeSomeReq: () => client.get<string>("/path"),
};
src/api.spec.ts (the test)

import api from "./api";
import axios, { AxiosResponse } from "axios";

jest.mock("axios");

const { get } = axios as jest.Mocked<typeof import("axios").default>;

describe("api", () => {
    it("should have created an axios instance", () => {
      expect(axios.create).toHaveBeenCalledWith({
        baseURL: "http://example.com:80/main",
      });
    });
})

working example

Teneff
  • 30,564
  • 13
  • 72
  • 103