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)는 제어된 방식으로 실제 객체의 동작을 모방하는 시뮬레이션 객체이다. 프로그래머는 일반적으로 자동차 디자이너가 충돌 테스트 더미를 사용하여 차량 충돌 시 인간의 동적 행동을 시뮬레이션하는 것과 거의 같은 방식으로 다른 물체의 동작을 테스트하기 위해 모의 물체를 만든다.
우선 실제로 동작하는 함수를 작성한다. 이 함수는 성공시 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
}
}
};
<T>
의 typeget<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:[]
});
});
});
});
jest.Mocked<typeof axios>
;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