how can i do a unit testing of axios.create mock with vitest?
Asked Answered
O

2

6

I'm learning unit testing in vue with Typescript and I want to test this function:

const getCLients =async (): Promise<Client[]> => {
    const {data} = await clientsApi.get('/clients')
    return data
}

But I got an error due to the clientsApi. My clients api is an axios instance and looks like this:

import axios from 'axios'

const clientsApi = axios.create({
   baseURL:import.meta.env.VITE_API_URL
})
export default clientsApi

My error is this:

TypeError: Cannot read properties of undefined (reading 'get') ❯ getCLients ../src/clients/composables/useClients.ts:14:41

14| const {data} = await clientsApi.get('/clients')

In my tests I have done the axios mock:

vi.mock('axios')
const mockedAxios = axios as jest.Mocked<typeof axios>;

mockedAxios.get.mockResolvedValue({
            data: mockClients,
})

I suposed that I had to make a mock of the axios.create but I have tried with a lot of ways but I always get the same type error. I need your help, how can you solve this?

Obstreperous answered 12/1, 2023 at 8:36 Comment(0)
F
1

Not sure if I'm on the right track as it just works on my end. I do vi.mock('axios') and have Error: spyOn could not find an object to spy uponenter code here. So I do vi.mock(the path to the instance ), and do vi.spyOn(the axios instance, 'get').mockResolvedValue and in your case, could be clientsApi.

Freudberg answered 1/3, 2023 at 0:38 Comment(0)
B
0

If, for instance, you're using axios.create() in your codebase to generate an AxiosInstance, you can mock this functionality as follows in your Vitest test file:

const mocks = vi.hoisted(() => ({
  get: vi.fn(),
  post: vi.fn(),
  // and any other request type you want to mock
}));

vi.mock('axios', async(importActual) => {
  const actual = await importActual<typeof import ('axios')>();

  const mockAxios = {
    default: {
      ...actual.default,
      create: vi.fn(() => ({
        ...actual.default.create(),
        get: mocks.get,
        post: mocks.post,
      })),
    },
  };

  return mockAxios;
});

Initially, we set up the mocks object that includes the get and post functions we want to mock. Using vi.hoisted(), we ensure these mocked functions are hoisted (i.e., moved to the top of the scope), allowing us to reference them within our vi.mock() function.

Then, we mock the entire axios module using vi.mock(). In order to maintain the existing functionality that we don't intend to mock, we employ importActual to import the real axios module. We then specify the parts we wish to mock, namely the create function and the get/post functions.

With these mocks in place, we can now spy on our mocked get and post methods. Here's an example of how to do it:

it('should call axios.get', async() => {
  mocks.get.mockResolvedValueOnce({
    data: {},
  });
  await clientsApi.getCLients();
  expect(mocks.get).toHaveBeenCalled(); // should return true
});

In the test case, we mock a resolved value for our get method and call the function we want to test (clientsApi.getCLients() in this case). We then check whether our mocked get function has been called using expect().toHaveBeenCalled().

This setup provides a controlled environment to test the interactions with the axios library in our code.

Britnibrito answered 3/7, 2023 at 20:51 Comment(2)
Please do not post the same answer to more than one question. Also, do not post ChatGPT answers, because they are plagiarism violating the Code of Conduct and officially BANNED on Stack Overflow](meta.https://mcmap.net/q/36206/-asp-net-site-default-document-in-subfolder). Please read: Why posting GPT and ChatGPT generated answers is not currently allowed.Daimyo
I came up with this solution on my own. I only used ChatGPT to reword my explanation; however, I didn't know that would be a problem because I just wanted to improve the clarity of my answer. Additionally, I tweaked this answer in the second question, they were the same question but my answer is different in the code snippets.Britnibrito

© 2022 - 2024 — McMap. All rights reserved.