I have a custom react hook, just to make a GET request with axios, and the file named as: useAxiosGet.ts, and the code is:
import {useMemo, useState} from "react";
import axios, {AxiosResponse} from "axios";
interface ErrorBody {
code: string,
message: string
}
export interface ErrorResponse {
status: number,
errorBody?: ErrorBody
}
export const useAxiosGet = <TResponse>(
requestUrl: string,
) => {
const [data, setData] = useState<TResponse>();
const [error, setError] = useState<ErrorResponse>();
const [loading, setLoading] = useState(false);
const getData = useMemo(() => {
return () => {
setLoading(true);
setError(undefined);
return axios.get(requestUrl)
.then((response: AxiosResponse<TResponse>) => {
const responseData = response.data;
setData(responseData);//update the date
return responseData
})
.catch(err => {
const errorResponse = {status: err.response.status, errorBody: err.response.data}
setError(errorResponse); //update the error
return Promise.reject(errorResponse) //return a Promise.reject
}).finally(() => {
setLoading(false)
});
};
}, []);
return {data, getData, setData, loading, error}
};
I made the resolved case test passed, but the reject case does not, and you can see that
I am returning the Promise.reject(errorResponse) in the.catch(), and I think this is the key point for the failed test. And my test code looks like below:
import {act, renderHook} from '@testing-library/react-hooks'
import axios from 'axios';
import MockAdapter from "axios-mock-adapter";
import {useAxiosGet} from "./useAxiosGet";
interface TProfile {
name: string
}
describe('useAxiosGet', () => {
let mockAxios: MockAdapter;
beforeAll(() => {
mockAxios = new MockAdapter(axios);
})
afterEach(() => {
mockAxios.reset()
})
afterAll(() => {
mockAxios.restore()
})
//This test passed
test('should get data for success request', async () => {
mockAxios.onGet("/id/1").reply(200, {name: 'nana'})
const {result, waitForNextUpdate} = renderHook(() => useAxiosGet<TProfile>('/id/1',))
act(() => {
result.current.getData()
})
await waitForNextUpdate()
expect(result.current.data).toStrictEqual({name: 'nana'})
expect(result.current.loading).toBeFalsy()
expect(result.current.error).toBe(undefined)
});
//This test not passed
test('should get error for failed request', async () => {
const errorBody = {
'code': 'NOT_FOUND',
'message': 'id 1 not found',
};
//Mock the request with a failed HTTP response
mockAxios.onGet("/id/1").reply(404, errorBody)
const {result, waitForValueToChange} = renderHook(() => useAxiosGet<TProfile>('/id/1',))
await waitForValueToChange(() => result.current.getData());
let errorResponse = {
status: 404,
errorBody: errorBody
};
expect(result.current.data).toStrictEqual(undefined);
expect(result.current.error).toStrictEqual(errorResponse);
})
})
I would like to test after the API called, the result.current.error should be the errorResponse expected, but I always get undefined :
test failed screenshot
I know there are something wrong with the test code, but I do not know the correct way to test the reject case, any one know how to do it?