MockTest with Typescript and Axios

Hwalyo·2022년 8월 12일
0
post-custom-banner

Axios MockTest

Mock Object

Mock Object는 테스트 더블(Test Double)중 하나 이며 위키피디아에서는 아래와 같이 정의 한다.

In object-oriented programming, mock objects are simulated objects that mimic the behavior of real objects in controlled ways. A programmer typically creates a mock object to test the behavior of some other object, in much the same way that a car designer uses a crash test dummy to simulate the dynamic behavior of a human in vehicle impacts.

객체 지향 프로그래밍에서 모의 객체(mock object)는 제어된 방식으로 실제 객체의 동작을 모방하는 시뮬레이션 객체이다. 프로그래머는 일반적으로 자동차 디자이너가 충돌 테스트 더미를 사용하여 차량 충돌 시 인간의 동적 행동을 시뮬레이션하는 것과 거의 같은 방식으로 다른 물체의 동작을 테스트하기 위해 모의 물체를 만든다.

utils.ts

우선 실제로 동작하는 함수를 작성한다. 이 함수는 성공시 Promise를 반환한다.

export const MOVIE_BASE_URL= 'https://imdb-api.com/en/API';
import { MOVIE_API_KEY } from "../API_KEY/api_keys";
import axios from "axios";

  interface movieType{
      items: object[]
      errorMessage: string
  }

  export const fetchMovie = async () => {
    const items: movieType['items']= [];
    try {
      return await axios.get<movieType>(`${MOVIE_BASE_URL}/BoxOffice/${MOVIE_API_KEY}`);
    } catch (error) {
      return {
        items: items
      }
    }
  };

Axios get, axiosResponse<T>의 type

get<T = any, R = AxiosResponse<T>, D = any>
(url: string, config?: AxiosRequestConfig<D>)
: Promise<R>;
export interface AxiosResponse<T = any, D = any>  {
  data: T;
  status: number;
  statusText: string;
  headers: AxiosResponseHeaders;
  config: AxiosRequestConfig<D>;
  request?: any;
}

get 메서드의 제네릭 <T>는 Response 안의 DATA의 타입이고 반환 타입은 Promise다.
즉, <T>는 서버에 반응받는 ResponseBody의 데이터의 타입을 뜻한다.

import axios from "axios";

import { MOVIE_BASE_URL, fetchMovie } from "../../utils/utils";
import {MOVIE_API_KEY} from '../../API_KEY/api_keys'
jest.mock("axios");
const mockedAxios= axios as jest.Mocked<typeof axios>;
describe("fetchUsers", () => {
  describe("when API call is successful", () => {
    it("should return movies list", async () => {
      // given
      const movieImtes = {
        items: [
          {
            id: "tt12593682",
            rank: "1",
            title: "Bullet Train",
            image:
              "https://m.media-amazon.com/images/M/MV5BMDU2ZmM2OTYtNzIxYy00NjM5LTliNGQtN2JmOWQzYTBmZWUzXkEyXkFqcGdeQXVyMTkxNjUyNQ@@._V1_UX128_CR0,3,128,176_AL_.jpg",
            weekend: "$30.0M",
            gross: "$30.0M",
            weeks: "1",
          },
          {
            id: "tt8912936",
            rank: "2",
            title: "DC League of Super-Pets",
            image:
              "https://m.media-amazon.com/images/M/MV5BYWI2NDg5M2MtMGMwYS00NzU1LWI1YzktYTg0ZDEwMjY4YmUwXkEyXkFqcGdeQXVyMTMzODk3NDU0._V1_UX128_CR0,3,128,176_AL_.jpg",
            weekend: "$11.1M",
            gross: "$45.0M",
            weeks: "2",
          },
        ],
        errorMessage:""
      };
      //axios get메서드에서 R = AxiosResponse<T>는  Pormise<R> 값의 타입을 가짐.
      //Promise가 성공했을 때, 임의의 데이터를 주입해줌.
      mockedAxios.get.mockResolvedValueOnce(movieImtes);

      // when
      const result = await fetchMovie();

      // then
      expect(axios.get).toHaveBeenCalledWith(`${MOVIE_BASE_URL}/BoxOffice/${MOVIE_API_KEY}`);
      expect(result).toEqual(movieImtes);
    });
  });

  describe("when API call fails", () => {
    it("should return empty movie list", async () => {
      // given
      const message = "Network Error";
      mockedAxios.get.mockRejectedValueOnce(new Error(message));

      // when
      const result = await fetchMovie();

      // then
      expect(axios.get).toHaveBeenCalledWith(`${MOVIE_BASE_URL}/BoxOffice/${MOVIE_API_KEY}`);
      expect(result).toEqual({
        items:[]
      });
    });
  });
});
  1. Mock Axios:jeast.mock("axios")로 axios 모듈을 Moking 해준다.
  2. const mockedAxios= axios as jest.Mocked<typeof axios>;
    • 타입스크립트에서 모킹된 axios 모듈의 type으로 지정해준다.
  3. 임의의 데이터를 응답 샘플로 생성하여 Axios 인스턴스에서 이를 반환하도록 합니다.
    • asios.get.mock Resolved ValueOnce(movieImtes).
    • asios.get.mockRejectedValueOnce(new Error(message))
  4. GET 요청을 테스트하고 있기 때문에 응답을 위해 axios.get을 사용한다.
  5. 테스트하는 함수를 호출합니다(여기서는 fetchMovie())
  6. toHaveBeenCalledWith()은 특정 매개변수로 모의함수가 동작하는지 확인한다.
  7. toEqual()을 통해 결과값을 비교하여 data 값이 같은지 확인한다.

Reference

https://vhudyma-blog.eu/3-ways-to-mock-axios-in-jest/
https://stackoverflow.com/questions/51275434/type-of-axios-mock-using-jest-typescript?rq=1
https://en.wikipedia.org/wiki/Mock_object

profile
꾸준하게글을작성해보자
post-custom-banner

0개의 댓글