Home > Software engineering >  Mock function not called and not resolving or returning mocked value in React jest API testing
Mock function not called and not resolving or returning mocked value in React jest API testing

Time:05-19

I am using jest to test the axios API calls. Mocking the API is not resolving or returning a value and mock function is not called. Here is my code for API call and testing.

This is the base service file that has postData function

import axios from 'axios';

const API_ENDPOINT = process.env.REACT_APP_API_ENDPOINT;

function setHeader(contentType:string, token:string|undefined) {
  return {
    'Accept': 'application/json',
    'Content-Type': contentType,
    'Authorization': `Bearer ${token}`,
  };
}

async function postData(path:string, contentType:string, token:string|undefined,
    payload:FormData | Record<string, any> | string) {
  return axios({
    method: 'post',
    url: `${API_ENDPOINT}${path}`,
    headers: setHeader(contentType, token),
    data: payload,
  });
}

export {postData}

This is the test file code that i have tried.

import '@testing-library/jest-dom';
import axios from 'axios';
import confirmProfile from '../../apis/onboard/confirmProfile';

jest.mock('axios');
const mockAxios=axios as jest.Mocked<typeof axios>;
const VALID_TOKEN='eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzZXNzaW9uIjoicmRjZDhpbXduOXl0YjZ5eTRrN3I4NnJsb3RjcnZ0cHkiLCJuYmYiOjE2NTI2NzYyNTguMzcwNTUyOCwiaXNzIjoiZ296ZWFsIn0.IR1hNOZPY4rcrykJgzrGkgfJM9vJNuveG-KS8BYaxnI';

it("Confirm profile original file with valid params",async ()=>{
    const res={confirmProfileData: { isSuccess: false }, 
        apiError: undefined,
        }
    mockAxios.post.mockResolvedValueOnce(res);
    const response = await confirmProfile(VALID_TOKEN);
    console.log('profile',response);
    expect(mockAxios.post).toHaveBeenCalledTimes(1);
    expect(response).toEqual(res);
})

Result of testing

 FAIL  src/__tests__/apis/Testing.test.ts
  ✕ Confirm profile original file with valid params (10 ms)

  ● Confirm profile original file with valid params

    expect(jest.fn()).toHaveBeenCalledTimes(expected)

    Expected number of calls: 1
    Received number of calls: 0

      27 |     const response = await confirmProfile(VALID_TOKEN);
      28 |     console.log('profile',response);
    > 29 |     expect(mockAxios.post).toHaveBeenCalledTimes(1);
         |                            ^
      30 |     expect(response).toEqual(res);
      31 | })
      32 |

      at Object.<anonymous> (src/__tests__/apis/Testing.test.ts:29:28)

  console.log
    profile { confirmProfileData: { isSuccess: true }, apiError: undefined }

      at Object.<anonymous> (src/__tests__/apis/Testing.test.ts:32:1)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        1.857 s, estimated 3 s

Mock function has not been called and the mocked value does not resolve or log

CodePudding user response:

The problem is caused by the fact that your code is not directly invoking the post function on the axios module instance and is instead doing it implicitly via a json parameter, whereas your test mock is looking for a direct axios.post call. There are 2 ways you can resolve this problem.

1. Change an implicit post call into an explicit one:

From:

axios({
    method: 'post',
    url: `${API_ENDPOINT}${path}`,
    headers: setHeader(contentType, token),
    data: payload,
  })

To:

axios.post(`${API_ENDPOINT}${path}`, payload, { headers: setHeader(contentType, token) })

2. Mock out the axios post call in the test suite set up:

From:

jest.mock("axios")

To

jest.mock("axios", () => {
  const expectedResponse = JSON.stringify({
    "access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxZDY2OTF",
    "issued_token_type": "token-type:access_token",
    "token_type": "Bearer",
    "expires_in": 3600,
    "scope": "consumer_profile:read:"
  });
  return () => new Promise((resolve) => resolve(expectedResponse));
})

This will mock out the implicit post call via a partial mock, however you will not have direct access to the post method, hence you will not be able to listen specifically to its calls.

  • Related