[ 살펴보기 ] Jest - Mock function
![[ 살펴보기 ] Jest - Mock function](https://cdn.hashnode.com/res/hashnode/image/upload/v1730360642412/d6249158-b290-4a93-a0bc-0a512226c08a.jpeg)
실제 코드에서 특정 function을 테스트 해야 할 때 mock function을 만들어 특정 function의 역할을 대신할 수 있다.
다음과 같이 callback을 parameter로 전달받는 function가 있다고 가정해보자.
export const listFn = (items, callback) => {
for (const item of items) {
callback(item);
}
}
위의 function을 테스트하기 위해 callback parameter로 전달할 function이 필요한데 이 때 mock function을 만들어 전달할 수 있다.
export const listFn = (items, callback) => {
for (const item of items) {
callback(item);
}
}
const mockCallback = jest.fn(x => 10 + x);
// mock function
test('Have the mock function been called twice?', () => {
listFn([1, 2], mockCallback);
expect(mockCallback.mock.calls).toHaveLength(2);
});
test('the first return value is 11?', () => {
listFn([1, 2], mockCallback);
expect(mockCallback.mock.results[0].value).toBe(11);
});
test("the first argument of the first call is 2?", () => {
listFn([2, 3], mockCallback);
console.log(mockCallback.mock.calls);
expect(mockCallback.mock.calls[0][0]).toBe(2);
});
test("the second argument of the first call is 3?", () => {
listFn([2, 3], mockCallback);
console.log(mockCallback.mock.calls);
expect(mockCallback.mock.calls[1][0]).toBe(3);
});
Mocking Axios
만약 axios를 통해 api reqeust를 포함하는 function을 테스트 해야 한다면 실제 axios request를 발생 시키는 대신 axios를 mock하여 해당 함수가 return하는 mock data를 미리 설정해두고 사용할 수 있다.
import axios from "axios";
jest.mock("axios");
const getUserList = async () => {
const result = await axios.get("example.com/users");
return result.data;
};
test("test getUserList", async () => {
const users = [
{ id: 1, name: "john" },
{ id: 2, name: "jane" },
];
const res = {
data: [
{ id: 1, name: "john" },
{ id: 2, name: "jane" },
],
};
const mockAxiosGet = axios.get as jest.MockedFunction<typeof axios.get>;
mockAxiosGet.mockResolvedValue(res);
const result = await getUserList();
expect(result).toEqual(users);
});
위의 예제에서 jest.mock(“axios”)를 통해 axios를 mock하고 axios.get의 mock version인 mockAxiosGet의 mockResolvedValue method를 통해 test code에서 axios.get이 성공적으로 실행되었을 때 어떤 response를 return해 주어야 하는지 설정하고 있다.
이제 test code에서 getUserList function을 실행하면 실제로 api request를 발생 시키는 대신 mockResolvedValue method에 설정한 값이 return된다.
Module 일부만 Mocking
만약 module의 일부만 mock function을 적용하고 싶으면 어떻게 할 수 있을까? 예를 들어 sum과 subtract util function이 있는 caclucate.ts module에서 sum function만 mock function을 적용하고 subtract function은 원래 function 그대로 사용하고 싶을 때 다음과 같이 mock function을 일부만 적용할 수 있다.
calculate.ts
export const sum = (firstNum: number, secondNum: number) =>
firstNum + secondNum;
export const subtract = (firstNum: number, secondNum: number) =>
firstNum - secondNum;
main.test.ts
import { subtract, sum } from "./calculate";
jest.mock("./calculate", () => {
const originalModule = jest.requireActual("./calculate");
return {
...originalModule,
sum: jest.fn((firstNum: number, secondNum: number) => {
return 1;
}),
};
});
test("Is sum result 1?", () => {
const sumResult = sum(5, 3);
expect(sumResult).toBe(1);
});
test("Is subtract result 2?", () => {
const subtractResult = subtract(5, 3);
expect(subtractResult).toBe(2);
});
위의 예제에서 sum function에 mock function을 적용해 return 값이 무조건 1이 되도록 설정하고 있다. 그렇기에 해당 test file에서 sum을 실행하면 return 값이 항상 1이 되지만 subtract function은 별도로 mock function을 적용하고 있지 않기에 원래 대로 동작한다.
Matchers for mock function
expect를 통해 mock function을 검사할 때 다음 matcher를 통해 mock function이 실행되었는지 혹은 특정 parameter를 전달 받아 실행 되었는지 등을 파악할 수 있다.
toHaveBeenCalled : test code가 실행될 때 mock 함수가 실행되었는지 확인한다.
export const listFn = (items, callback) => { for (const item of items) { callback(item); } }; const mockCallback = jest.fn((x) => 10 + x); test("Have the mock function been called?", () => { listFn([1, 2], mockCallback); expect(mockCallback).toHaveBeenCalled(); });toHaveBeenCalledWith : mock function이 실행될 때 특정한 parameter를 전달 받아 실행된 적이 있는지 확인한다.
export const listFn = (items, callback) => { for (const item of items) { callback(item); } }; const mockCallback = jest.fn((x) => 10 + x); test("Have the mock function been called?", () => { listFn([1, 2], mockCallback); expect(mockCallback).toHaveBeenCalledWith(1); });toHaveBeenLastCalledWith : mock 함수가 마지막으로 실행되었을 때 특정 parameter를 전달 받아 실행되었는지 확인한다.
export const listFn = (items, callback) => { for (const item of items) { callback(item); } }; const mockCallback = jest.fn((x) => 10 + x); test("Have the mock function been called?", () => { listFn([1, 2], mockCallback); expect(mockCallback).toHaveBeenLastCalledWith(2); });
![[ 살펴보기 ] RDB - Relationships](https://cdn.hashnode.com/res/hashnode/image/upload/v1739711556668/48dc9e84-a621-42aa-9c9f-5fc5c436f0ec.jpeg)
![[ 살펴보기 ] MySQL - Data types](https://cdn.hashnode.com/res/hashnode/image/upload/v1739593589113/530f8704-4d27-42c9-a451-bb5c63150b99.jpeg)
![[ 살펴보기 ] TypeORM - Transactions, Migration](https://cdn.hashnode.com/res/hashnode/image/upload/v1739106042581/980b8133-61d4-406a-a026-65be9c28eace.jpeg)
![[ 살펴보기 ] TypeORM - Relations](https://cdn.hashnode.com/res/hashnode/image/upload/v1738666874402/b688bd0b-b6bb-4f43-87d8-c1b46b59f1b7.jpeg)
![[ 살펴보기 ] TypeORM - Basics](https://cdn.hashnode.com/res/hashnode/image/upload/v1738666803591/bef5df17-7dc7-4123-ae55-004d5042df39.jpeg)