본문 바로가기
React.JS

[React]Axios 에러테스트 feat.jest

by hans-j 2024. 10. 24.

React typescript프로젝트에서 axios 에러 테스트 진행! (jest로 함)

여기서 주의할 부분은

 

API 호출 성공 후 에러 상태 반환에 대한 테스트!!

 

//에러 핸들링 파일
import axios, { AxiosError } from 'axios';
import ValidationMessages from '../components/Validations/ValidationMessages';

const errorMessages: Record<number, string> = {
    40000: ValidationMessages.LOGIN_FAILED,
    40001: ValidationMessages.INVALID_FORM,
    40002: ValidationMessages.EXIST_USER,
    40003: ValidationMessages.MISSED_FORM,
    40102: ValidationMessages.INVALID_PASSWORD_LENGTH,
    40401: ValidationMessages.MISSED_RESOURCE,
    50000: ValidationMessages.SERVER_ERROR,
};

export const handleApiError = (
    error: AxiosError,
    setMessage: (message: string) => void
) => {
    if (axios.isAxiosError(error)) {
        const status = error.response?.status;

        const message =
            status !== undefined
                ? errorMessages[status]
                : ValidationMessages.UNKNOWN_ERROR;
        setMessage(message);
    } else {
        setMessage(ValidationMessages.UNKNOWN_ERROR);
    }
};

 

 

//테스트 코드
import axios, { AxiosError } from 'axios';
import { handleApiError } from '../../utils/handleApiError';
import ValidationMessages from '../../components/Validations/ValidationMessages';

jest.spyOn(axios, 'isAxiosError').mockImplementation(
    (error) => error.isAxiosError === true
);
describe('handleApiError', () => {
    let setMessage: jest.Mock;

    beforeEach(() => {
        setMessage = jest.fn(); // setMessage를 모킹하여 메시지를 설정하는 함수로 사용
    });

    test.each([
        [40001, ValidationMessages.INVALID_FORM],
        [40002, ValidationMessages.EXIST_USER],
        [50000, ValidationMessages.SERVER_ERROR],
    ])('handles status code %d correctly', (status, expectedMessage) => {
        const error: AxiosError = {
            isAxiosError: true,
            response: {
                status: status, // 숫자로 변환하여 설정
                data: {},
                headers: {},
            },
            config: {},
            toJSON: () => ({}),
        } as AxiosError;
        console.log('error', error.response?.status);
        handleApiError(error, setMessage); // 에러를 처리하는 함수 호출
        // setMessage 호출 로그
        console.log('setMessage calls:', setMessage.mock.calls);
        expect(setMessage).toHaveBeenCalledWith(expectedMessage); // 올바른 메시지가 설정되었는지 확인
    });
});


아무튼 간단한 코드설명은 내가 예상한 에러 상태가아니면 UNKNOWN_ERROR를 띄움

그런데 문제발생

 

 

 

 

문제 내용 : 계~속 UNKNOWN_ERROR 메세지를 반환함..

 

 

문제는 아래의 코드

jest.mock('axios'); // Mock axios

 

위의 코드가 에러를 발생시켰던 이유는

 

 

문제 발생이유는!!

  • jest.mock('axios')를 사용하면 Axios 모듈 전체가 모킹되어, 내부 함수들(예: isAxiosError)도 모의 객체로 대체됨.
  • isAxiosError가 올바르게 정의되지 않아서 항상 undefined 또는 false를 반환했고, 그 결과로 에러 핸들러는 Axios 에러로 인식하지 못하고 UNKNOWN_ERROR를 반환하게 함.
  • 통신 성공 후 오류 상태를 처리할 때는 Axios의 에러 판별 기능(isAxiosError)이 중요하므로, 이를 별도로 모킹해야 함.
  • API 호출 자체가 실패할 때는 jest.mock('axios')를 사용하여 Axios 전체를 모킹하는 게 유용합니다. 예를 들어, 네트워크 오류나 서버 연결 실패 같은 상황을 모킹하기에 적합.
  • API 호출은 성공했지만, 에러 상태를 반환하는 경우는 jest.mock('axios')를 사용하면 isAxiosError가 모킹되어 제대로 동작하지 않으므로, 이런 상황에서는 jest.spyOn으로 필요한 부분만 모킹하는 것이 적절.

결론 :

API 호출 통신 실패 테스트시  ->

jest.mock('axios')

 

API호출 통신 성공 했으나 에러상태 반환 테스트시 ->

jest.spyOn(axios, 'isAxiosError').mockImplementation(
    (error) => error.isAxiosError === true
);