Skip to content

Commit 3f3b415

Browse files
committedSep 12, 2023
add jest
1 parent 7d9984b commit 3f3b415

File tree

1 file changed

+109
-0
lines changed

1 file changed

+109
-0
lines changed
 

‎_posts/2023-09-12-jest-mocking.md

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
---
2+
title: Jest_mocking
3+
layout: post
4+
---
5+
6+
### mocking
7+
먼저 `mock`이란 모조품이라는 뜻으로 `mocking`은 테스트를 독립시키기 위해 의존성(일반적으로 import하는 모듈들)들을 개발자가 컨트롤하고 검사할 수 있는 오브젝트로 바꾸는 것을 말한다.
8+
9+
만약 `mocking`을 하지 않고 직접 의존성들을 사용해서 테스트를 하게 되면 아래와 같은 문제점이 있을 수 있다.
10+
- 의존성(예를들어 데이터베이스나 다른 앱)들에서 정보를 가져오는 것은 속도가 확실히 느리기에 Testing 속도를 현저하게 저하 시킬 수 있다.
11+
- 또한 테스트에서 사용했던 정보들을 다시 초기화 해줘야하는 것에 많은 노력과 시간이 들어간다.
12+
- 테스트를 위한 직접적인 코드를 작성해 줘야하는데 노력과 시간이 들어간다. 의존성에서 문제가 생기면 테스트 자체가 무의미해진다.
13+
- 이중 제일 문제는 특정 로직만을 테스트를 하기 원하는 단위 테스트의 본질에서 벗어난다.
14+
15+
`mocking`은 이런 상황에서 실제 처럼 행동하는 것처럼 보이는 가짜 객체를 생성해준다. 또한 테스트가 존재하는 동안 해당 객체가 어떤 동작을 했는지 기억하기에 검증을 진행할 수 있게 해준다.
16+
17+
18+
### jset.fn()
19+
jest에서는 mock function을 생성할 수 있도록 `jest.fn()`함수를 제공합니다.
20+
```
21+
const mockFn = jest.fn();
22+
23+
mockFn() //undefined
24+
mockFn(1) //undefined
25+
mockFn("a") //undefined
26+
```
27+
아직 어떤 결과같을 가질지 알려주지 않았기에 결과값은 모두 `undefined`로 나오게 된다.
28+
```
29+
mockFn.mockReturnValue("I am a mock!");
30+
mockFn() // I am a mock
31+
32+
mockFn.mockResolvedValue("I am a mock!");
33+
mockFn().then((result) =>
34+
console.log(result) // I am a mock!
35+
}
36+
mockFn.mockImplementation((name) => `I am ${name}!`);
37+
console.log(mockFn("Dale")); // I am Dale!
38+
```
39+
`mockReturnValue` 이걸로 mock 함수의 return 값을 선언해줄 수 있다.
40+
`mockResolvedValue` 이걸로는 Promise로 return 하는 값을 선언해줄 수 있다.
41+
`mockImplementation` 이걸로는 아예 함수를 구현해볼 수 있다.
42+
43+
44+
### jest.spyOn()
45+
jest에서 일부 함수들의 구현을 가짜로 대체하지 않고 해당 함수의 호출 여부와 어떻게 호출 되었는지만을 알아내야할 때 사용한다. 즉 기존 함수에 spy를 붙여 어떻게 실행이 됐는지 감시를 할 수 있게 한다고 보면 된다.
46+
```
47+
const calculator = {
48+
add: (a, b) => a + b,
49+
};
50+
51+
const spyFn = jest.spyOn(calculator, "add");
52+
53+
const result = calculator.add(2, 3);
54+
55+
expect(spyFn).toBeCalledTimes(1); //true
56+
expect(spyFn).toBeCalledWith(2, 3); //true
57+
expect(result).toBe(5); //true
58+
```
59+
60+
### jest.fn() vs jest.spyOn()
61+
- `jest.fn()`는 새로운 가짜 함수를 생성하고 주로 함수를 완전히 대체 하거나 함수 호출에 대한 반환값을 제어하기 위해 사용된다.
62+
- `jest.spyOn()`은 이미 존재하는 객체의 메서드 또는 함수를 mocking 하거나 추적하기 위해 사용 된다.
63+
- 이때 실제 구현은 유지한 체ㅐ로 해당 함수 호출 정보를 추첮하고 반환값을 조작할 수 있다.
64+
65+
둘다 사용하는 예제
66+
```
67+
// 외부 의존성: axios 모듈을 모의(Mock)화
68+
const axios = require('axios');
69+
70+
// 내부 메서드: 특정 기능을 수행하는 함수
71+
function fetchDataFromAPI() {
72+
return axios.get('https://api.example.com/data');
73+
}
74+
75+
// 테스트 스위트
76+
describe('Example Test Suite', () => {
77+
// axios.get을 모의(Mock)하고 반환값 설정
78+
const axiosGetMock = jest.fn();
79+
axios.get = axiosGetMock;
80+
81+
// fetchDataFromAPI 함수 내부에서 axios.get을 스파이(Spy)
82+
test('fetchDataFromAPI should make a network request', async () => {
83+
// axios.get 스파이(Spy) 설정
84+
axiosGetMock.mockResolvedValue({ data: 'mocked data' });
85+
86+
// fetchDataFromAPI 함수 호출
87+
const result = await fetchDataFromAPI();
88+
89+
// axios.get이 호출되었는지 확인
90+
expect(axiosGetMock).toHaveBeenCalled();
91+
92+
// 결과 확인
93+
expect(result.data).toBe('mocked data');
94+
});
95+
96+
// 내부 메서드의 동작 테스트
97+
test('internal method should work', () => {
98+
// 내부 메서드 호출
99+
const result = internalMethod();
100+
101+
// 결과 확인 및 검증 로직 추가
102+
expect(result).toEqual(/* 기대값 */);
103+
});
104+
});
105+
```
106+
107+
참조
108+
- [Jest의 jest.fn(), jest.spyOn()를 이용한 함수 모킹](https://www.daleseo.com/jest-fn-spy-on/)
109+
- [[번역] Jest Mocks에 대한 이해](https://minoo.medium.com/%EB%B2%88%EC%97%AD-jest-mocks%EC%97%90-%EB%8C%80%ED%95%9C-%EC%9D%B4%ED%95%B4-34f75b0f7dbe)

0 commit comments

Comments
 (0)
Please sign in to comment.