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.