An open API service indexing awesome lists of open source software.

https://github.com/ssi02014/jest_tutorial

โœจ Jest Tutorial
https://github.com/ssi02014/jest_tutorial

javascript jest

Last synced: 8 months ago
JSON representation

โœจ Jest Tutorial

Awesome Lists containing this project

README

          

# ๐Ÿ’ป Jest Tutorial

## ๐Ÿ“‘ ์‹œ์ž‘
### ํŒจํ‚ค์ง€ ์„ค์น˜
```
yarn add jest
npm install jest --save-dev
```


## โœจ ํ…Œ์ŠคํŠธ ํŒŒ์ผ
```
1. (ํŒŒ์ผ์ด๋ฆ„).test.js
2. __tests__
```
- `npm test(or yarn test)` ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ํ”„๋กœ์ ํŠธ ๋‚ด์˜ ๋ชจ๋“  ํ…Œ์ŠคํŠธ ํŒŒ์ผ๋“ค์„ ์ฐพ์•„์„œ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•œ๋‹ค.
- ์ง์ ‘ ์„ ํƒํ•œ ํ…Œ์ŠคํŠธ ํŒŒ์ผ๋งŒ ์‹คํ–‰์‹œํ‚ค๊ณ  ์‹ถ์œผ๋ฉด `npm test (๊ฒฝ๋กœ ๋ฐ ํŒŒ์ผ ์ด๋ฆ„)`์œผ๋กœ ์‹คํ–‰ํ•˜๋ฉด ๋œ๋‹ค.


## ๐Ÿ”– ์œ ์šฉํ•œ Matchers ์˜ˆ์ œ
- Matchers ์ฐธ๊ณ  ์‚ฌ์ดํŠธ: https://jestjs.io/docs/en/expect


### ๐Ÿƒโ€โ™‚๏ธ 1. toBe
```js
// fn.js
const fn = {
add: (num1, num2) => num1 + num2,
};

module.exports = fn;
```
```js
// fn.test.js
const fn = require("./fn");

test("1์€ 1์ด์•ผ", () => {
expect(1).toBe(1);
});

test("3๋”ํ•˜๊ธฐ 3์€ 5๊ฐ€ ์•„๋‹ˆ์•ผ", () => {
expect(fn.add(3, 3)).not.toBe(5);
});
```
- `expect`์— ๊ฒ€์ฆํ•  ๊ฐ’์„ ๋„ฃ๊ณ , `toBe`์— ๊ธฐ๋Œ€๋˜๋Š” ๊ฐ’์„ ๋„ฃ๋Š”๋‹ค.
- `not`์€ ๋ถ€์ •์„ ์˜๋ฏธํ•œ๋‹ค.


### ๐Ÿƒโ€โ™‚๏ธ 2. toEqual
```js
// fn.js
const fn = {
add: (num1, num2) => num1 + num2,
makeUser: (name, age) => {
return {
name,
age,
};
},
};
module.exports = fn;
```
```js
// fn.test.js
test("2๋”ํ•˜๊ธฐ 3์€ 5์•ผ", () => {
expect(fn.add(2, 3)).toEqual(5);
});

test("2๋”ํ•˜๊ธฐ 3์€ 5์•ผ", () => {
expect(fn.add(2, 3)).toBe(5);
});

test("์ด๋ฆ„๊ณผ ๋‚˜์ด๋ฅผ ์ „๋‹ฌ๋ฐ›์•„์„œ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ค˜", () => {
expect(fn.makeUser("minjae", 27)).toEqual({ name: "minjae", age: 27 });
});
```
- ์ผ๋ฐ˜์ ์ธ ๊ฐ’์€ `toBe`์™€ `toEqual`์€ ๋™์ผํ•œ ๊ธฐ๋Šฅ์„ ํ•œ๋‹ค.
- ํ•˜์ง€๋งŒ ๋ฐฐ์—ด์ด๋‚˜ ๊ฐ์ฒด๋Š” ์žฌ๊ท€์ ์œผ๋กœ ๋Œ๋ฉด์„œ ๊ฐ’์„ ํ™•์ธํ•˜๊ธฐ ๋•Œ๋ฌธ์— `toBe`๊ฐ€ ์•„๋‹Œ `toEqual`์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. (`toBe`๋Š” ์˜ค๋ฅ˜ ๋ฐœ์ƒ)


### ๐Ÿƒโ€โ™‚๏ธ 3. toStrictEqual
```js
// fn.js
const fn = {
add: (num1, num2) => num1 + num2,
makeUser: (name, age) => {
return {
name,
age,
gender: undefined,
};
},
};
module.exports = fn;
```
```js
// fn.test.js
const fn = require("./fn");

test("์ด๋ฆ„๊ณผ ๋‚˜์ด๋ฅผ ์ „๋‹ฌ๋ฐ›์•„์„œ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ค˜", () => {
expect(fn.makeUser("minjae", 27)).toEqual({
name: "minjae",
age: 27
});
});

test("์ด๋ฆ„๊ณผ ๋‚˜์ด๋ฅผ ์ „๋‹ฌ๋ฐ›์•„์„œ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ค˜", () => {
expect(fn.makeUser("minjae", 27)).toStrictEqual({
name: "minjae",
age: 27
});
});
```
- ์œ„ ์˜ˆ์ œ์—์„œ `toEqual`์€ ํ…Œ์ŠคํŠธ๋ฅผ ํ†ต๊ณผํ•˜์ง€๋งŒ `toStrictEqual`์€ ํ…Œ์ŠคํŠธ๋ฅผ ํ†ต๊ณผํ•˜์ง€ ๋ชปํ•œ๋‹ค. ์ฆ‰ `toStrictEqual`์€ ์ข€ ๋” ์—„๊ฒฉํ•œ ํ…Œ์ŠคํŠธ ๋ฐฉ๋ฒ•์ด๋‹ค.
- `toStrictEqual` ์˜ˆ์ œ๊ฐ€ ํ†ต๊ณผํ•˜๋ ค๋ฉด gender ํ‚ค์— undefined ๊ฐ’์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๋œ๋‹ค.


### ๐Ÿƒโ€โ™‚๏ธ 4. toBeNull, toBeUndefined, toBeDefined
```js
// fn.test.js
test("null์€ null์ด๋‹ค.", () => {
expect(null).toBeNull();
});

test("undefined๋Š” undefined์ด๋‹ค.", () => {
expect(undefined).toBeUndefined();
});

test("x๋Š” ์ •์˜๋˜์–ด ์žˆ๋‹ค.", () => {
const x = 1;
expect(x).toBeDefined();
});
```
- `toBeNull`์€ null์ด๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผํ•œ๋‹ค.
- `toBeUndefined`๋Š” ๊ฐ’์ด undefined์ด๋ฉด ํ†ต๊ณผํ•œ๋‹ค.
- `toBeDefined`๋Š” ๊ฐ’์ด ์ •์˜๋˜์–ด ์žˆ์œผ๋ฉด ํ†ต๊ณผํ•œ๋‹ค.


### ๐Ÿƒโ€โ™‚๏ธ 5. toBeTruthy, toBeFalsy
```js
// fn.test.js
//fn์€ ์œ„์— ์˜ˆ์ œ ์ฝ”๋“œ ์ฐธ๊ณ 
test("0์€ false์ด๋‹ค.", () => {
expect(fn.add(1, -1)).toBeFalsy();
});

test("1์€ true์ด๋‹ค.", () => {
expect(fn.add(2, -1)).toBeTruthy();
});
```
- `toBeTruthy`์€ ๊ฐ’์ด true์ด๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผํ•œ๋‹ค.
- `toBeFalsy`์€ ๊ฐ’์ด false์ด๋ฉด ํ…Œ์ŠคํŠธ๊ณผ ํ†ต๊ณผํ•œ๋‹ค.


### ๐Ÿƒโ€โ™‚๏ธ 6. toBeGreaterThan, toBeGreaterThanOrEqual, toBeLessThan, toBeLessThanOrEqual
```js
// fn.test.js
test("ID๋Š” 10์ž ์ดํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.", () => {
const id = "THE_BLACK";
expect(id.length).toBeGreaterThan(5);
});

test("ID๋Š” 10์ž ์ดํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.", () => {
const id = "THE_BLACK";
expect(id.length).toBeLessThanOrEqual(10);
});
```
- `toBeGreaterThan`์€ ๊ฐ’์ด ํฌ๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผํ•œ๋‹ค.
- `toBeGreaterThanOrEqual`์€ ๊ฐ’์ด ํฌ๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผํ•œ๋‹ค.
- `toBeLessThan`์€ ๊ฐ’์ด ์ž‘์œผ๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผํ•œ๋‹ค.
- `toBeLessThanOrEqual`์€ ๊ฐ’์ด ์ž‘๊ฑฐ๋‚˜ ๊ฐ™์œผ๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผํ•œ๋‹ค.


### ๐Ÿƒโ€โ™‚๏ธ 7. toBeCloseTo
```js
// fn.test.js
test("0.1๋”ํ•˜๊ธฐ 0.2๋Š” 0.3dlek.", () => {
expect(fn.add(0.1, 0.2)).toBeCloseTo(0.3);
});
```
- ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ 0.1 ๋”ํ•˜๊ธฐ 0.2๋Š” 0.3์ด ์•„๋‹ˆ๋‹ค. 0.300000000004์ด๋‹ค. ์ฆ‰, ์†Œ์ˆ˜์ ์„ ์ •ํ™•ํ•˜๊ฒŒ ๊ณ„์‚ฐํ•˜์ง€ ๋ชปํ•œ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— `toBe`๋‚˜ `toEqual`์„ ์‚ฌ์šฉํ•˜๋ฉด ํ…Œ์ŠคํŠธ ํ†ต๊ณผ๊ฐ€ ๋˜์ง€ ๋ชปํ•œ๋‹ค.
- ์ด๋Ÿด๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ `toBeCloseTo`์ด๋‹ค. `toBeCloseTo`๋Š” ๊ทผ์‚ฌ๊ฐ’์ธ์ง€ ํŒ๋ณ„ํ•ด์ค€๋‹ค.


### ๐Ÿƒโ€โ™‚๏ธ 8. toMatch
```js
// fn.test.js
test("Hello World์— H๋ผ๋Š” ๊ธ€์ž๊ฐ€ ์žˆ๋‚˜?", () => {
expect("Hello World").toMatch(/H/); // /H/ ๋’ค์— i๋ฅผ ๋ถ™์ด๋ฉด ๋Œ€์†Œ๋ฌธ์ž ๊ตฌ๋ถ„์ด ์—†์–ด์ง„๋‹ค.
});

test("Hello World์— H๋ผ๋Š” ๊ธ€์ž๊ฐ€ ์žˆ๋‚˜?", () => {
expect("Hello World").toMatch(/h/i); // /h/ ๋’ค์— i๋ฅผ ๋ถ™์ด๋ฉด ๋Œ€์†Œ๋ฌธ์ž ๊ตฌ๋ถ„์ด ์—†์–ด์ง„๋‹ค.
});
```
- `toMatch`๋Š” ๋ฌธ์ž์—ด์€ ํŒ๋ณ„ํ•ด์ค€๋‹ค. ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผํ•œ๋‹ค.


### ๐Ÿƒโ€โ™‚๏ธ 9. toContain
```js
// fn.test.js
test("Hello World์— H๋ผ๋Š” ๊ธ€์ž๊ฐ€ ์žˆ๋‚˜?", () => {
const user = "Mike";
const userList = ["Tom", "Mike", "Kai"];

expect(userList).toContain(user);
});
```
- `toContain`๋Š” ๋ฐฐ์—ด์•ˆ์— ํŠน์ • ์š”์†Œ๊ฐ€ ์žˆ๋Š”์ง€ ํŒ๋ณ„ํ•ด์ค€๋‹ค. ์žˆ์œผ๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผํ•œ๋‹ค.


### ๐Ÿƒโ€โ™‚๏ธ 10. toThrow
```js
const fn = {
// ...
throwErr: () => {
throw new Error("error");
},
};

module.exports = fn;
```
```js
// fn.test.js
test("์ด๊ฑฐ ์—๋Ÿฌ๊ฐ€ ๋‚˜๋‚˜์š”?", () => {
expect(() => fn.throwErr()).toThrow();
});

test("์ด๊ฑฐ ์—๋Ÿฌ๊ฐ€ ๋‚˜๋‚˜์š”?", () => {
expect(() => fn.throwErr()).toThrow("error");
});
```
- `throwErr`๋Š” ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผ๋œ๋‹ค.
- ๋งŒ์•ฝ `thThrow` ์ธ์ˆ˜๋กœ ํŠน์ • ์š”์†Œ๋ฅผ ๋„ฃ์œผ๋ฉด ๋น„๊ต๋ฅผํ•ด์„œ ์ถœ๋ ฅ๊ฐ’๊ณผ ์ธ์ˆ˜๊ฐ€ ๊ฐ™์œผ๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผํ•œ๋‹ค.


## ๐Ÿ”– ๋น„๋™๊ธฐ ์ฝ”๋“œ ํ…Œ์ŠคํŠธ
### ๐Ÿƒโ€โ™‚๏ธ 1. ๊ธฐ๋ณธ ์˜ˆ์ œ
```js
// fnAsync.js
const fnAsync = {
add: (num1, num2) => num1 + num2,
getName: (callback) => {
const name = "Mike";
setTimeout(() => {
callback(name);
}, 3000);
},
};

module.exports = fnAsync;
```
```js
// fnAsync.test.js
test("3์ดˆ ํ›„์— ๋ฐ›์•„์˜จ ์ด๋ฆ„์€ Mike", () => {
const callback = (name) => {
expect(name).toBe("Mike");
};
fn.getName(callback);
});
```
- ์œ„ ์˜ˆ์ œ์ฒ˜๋Ÿผ ์‹คํ–‰ํ•˜๋ฉด jest๋Š” ์ฝ”๋“œ ๋์— ๋‹ค๋‹ค๋ฅด๋ฉด ๊ทธ๋ƒฅ ์ฝ”๋“œ๊ฐ€ ์ข…๋ฃŒ๋œ๋‹ค.


```js
// fnAsync.test.js
test("3์ดˆ ํ›„์— ๋ฐ›์•„์˜จ ์ด๋ฆ„์€ Mike", (done) => {
const callback = (name) => {
expect(name).toBe("Mike");
done();
};
fn.getName(callback);
});
```
- ์œ„ ์˜ˆ์ œ์ฒ˜๋Ÿผ test ๋ฉ”์„œ๋“œ์— ๋‘๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ ์ฝœ๋ฐฑํ•จ์ˆ˜์— ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ `done`์„ ๋„ฃ๊ณ  ์ด done์ด ํ˜ธ์ถœ๋˜๋ฉด ์ข…๋ฃŒ๋˜๊ฒŒ๋” ์ž‘์„ฑํ•˜๋ฉด ์ œ๋Œ€๋กœ ๋น„๋™๊ธฐ ์ฝ”๋“œ ํ…Œ์ŠคํŠธ๊ฐ€ ๊ฐ€๋Šฅํ•ด์ง„๋‹ค.
- ๋งŒ์•ฝ `done`์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„ฃ๊ณ  ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฉด ํ…Œ์ŠคํŠธ๋Š” ์‹คํŒจํ•˜๊ฒŒ ๋œ๋‹ค.


### ๐Ÿƒโ€โ™‚๏ธ 2. try/catch
```js
// fnAsync.test.js
test("3์ดˆ ํ›„์— ๋ฐ›์•„์˜จ ์ด๋ฆ„์€ Mike", (done) => {
const callback = (name) => {
try {
expect(name).toBe("Mike");
done();
} catch (e) {
done();
}
};
fn.getName(callback);
});
```
- ๋งŒ์•ฝ API ์—๋Ÿฌ๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด `try/catch`๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.


### ๐Ÿƒโ€โ™‚๏ธ 3. Promise ํ›„์† ์ฒ˜๋ฆฌ ๋ฉ”์„œ๋“œ
```js
// fnAsync.js
const fnAsync = {
// ...
getAge: () => {
const age = 27;
return new Promise((res, rej) => {
setTimeout(() => {
res(age);
// rej("error");
}, 3000);
});
},
};
module.exports = fnAsync;
```
```js
// fnAsync.test.js
test("3์ดˆ ํ›„์— ๋ฐ›์•„์˜จ ๋‚˜์ด๋Š” 27", () => {
return fn.getAge().then((age) => {
expect(age).toBe(27);
});
});

// ์œ„ ์˜ˆ์ œ๋ณด๋‹ค ์ข€ ๋” ๊ฐ„๊ฒฐํ•œ resolves, rejects๋ฅผ ์‚ฌ์šฉํ•œ ์ฝ”๋“œ
test("3์ดˆ ํ›„์— ๋ฐ›์•„์˜จ ๋‚˜์ด๋Š” 27", () => {
return expect(fn.getAge()).resolves.toBe(27);
});

test("3์ดˆ ํ›„์— ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.", () => {
return expect(fn.getAge()).rejects.toMatch("error");
});
```
- Promise ์ฝ”๋“œ๋ฅผ ํ…Œ์ŠคํŠธํ•  ๋•Œ๋Š” `return`์„ ๊ผญ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. ์•ˆ๊ทธ๋Ÿฌ๋ฉด ์ œ๋Œ€๋กœ ๋œ ํ…Œ์ŠคํŠธ๊ฐ€ ๋ถˆ๊ฐ€๋Šฅ!


### ๐Ÿƒโ€โ™‚๏ธ 4. async/await
```js
// fnAsync.test.js
test("3์ดˆ ํ›„์— ๋ฐ›์•„์˜จ ๋‚˜์ด๋Š” 27", async () => {
const age = await fn.getAge();
expect(age).toBe(30);
});

test("3์ดˆ ํ›„์— ๋ฐ›์•„์˜จ ๋‚˜์ด๋Š” 27", async () => {
await expect(fn.getAge()).resolves.toBe(27);
});
```


## ๐Ÿ”– ํ…Œ์ŠคํŠธ ์ „ํ›„ ์ž‘์—…
### ๐Ÿƒโ€โ™‚๏ธ 1. beforeEach
```js
let num = 0;
beforeEach(() => {
num = 0;
});
test("0 ๋”ํ•˜๊ธฐ 1์€ 1์ด์•ผ", () => {
num = fn.add(num, 1);
expect(num).toBe(1);
});
```
- beforeEach๋Š” ๊ฐ ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํ–‰ํ•  ๋•Œ๋งˆ๋‹ค ์‹คํ–‰๋˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.


### ๐Ÿƒโ€โ™‚๏ธ 2. afterEach
```js
let num = 0;
afterEach(() => {
num = 0;
});
test("0 ๋”ํ•˜๊ธฐ 1์€ 1์ด์•ผ", () => {
num = fn.add(num, 1);
expect(num).toBe(1);
});
```
- afterEach๋Š” ๊ฐ ํ…Œ์ŠคํŠธ๊ฐ€ ์ข…๋ฃŒํ•  ๋•Œ๋งˆ๋‹ค ์‹คํ–‰๋˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.


### ๐Ÿƒโ€โ™‚๏ธ 3. beforeAll/afterAll
```js
beforeAll(async () => {
user = await fn.connectUserDB();
});
afterAll(() => {
return fn.disconnectDB;
});
```
- beforeAll์€ ์ „์ฒด ํ…Œ์ŠคํŠธ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ฒ˜์Œ ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํ–‰ํ•  ๋•Œ ์‹คํ–‰๋œ๋‹ค.
- afterAll์€ ์ „์ฒด ํ…Œ์ŠคํŠธ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํ…Œ์ŠคํŠธ๊ฐ€ ๋ชจ๋‘ ์ข…๋ฃŒ๋  ๋•Œ ์‹คํ–‰๋œ๋‹ค.
- db์—ฐ๊ฒฐ์ด๋‚˜ ์ข…๋ฃŒ๋Š” ์ฒ˜์Œ๊ณผ ๋์—๋งŒ ์‹คํ–‰๋˜๋ฉด๋˜์„œ ๋งค๋ฒˆ ์‹คํ–‰๋˜๋Š” beforeEach๋‚˜ afterEach๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋ณด๋‹ค๋Š” beforeAll, afterAll์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.


### ๐Ÿƒโ€โ™‚๏ธ 4. describe
```js
describe("Car ๊ด€๋ จ ์ž‘์—…", () => {
let car = {};

beforeAll(async () => {
car = await fn.connectCarDB();
});
afterAll(() => {
return fn.disconnectCarDB;
});

test("์ด๋ฆ„์€ Minjae", () => {
expect(car.brend).toBe("bmw");
});
test("๋‚˜์ด๋Š” 27", () => {
expect(car.name).toBe("z4");
});
test("์ด๋ฆ„์€ Minjae", () => {
expect(car.color).toBe("red");
});
});
```
- describe๋Š” ํ…Œ์ŠคํŠธ ํŒŒ์ผ์— ๋งŽ์€ ์ˆ˜์˜ ํ…Œ์ŠคํŠธ ํ•จ์ˆ˜๊ฐ€ ์ž‘์„ฑ๋œ ๊ฒฝ์šฐ, ์—ฐ๊ด€๋œ ํ…Œ์ŠคํŠธ ํ•จ์ˆ˜๋“ค๋ผ๋ฆฌ ๊ทธ๋ฃนํ™”ํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.
- describe๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ testํ•จ์ˆ˜ ๋Œ€์‹  `it`ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ๋„ ํ•˜๋Š”๋ฐ, ์ด ๋‘ ํ•จ์ˆ˜๋Š” ์™„์ „ํ•œ ๋™์ผํ•œ ๊ธฐ๋Šฅ์„ ํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค. Mocha๋‚˜ Jasmin ๊ฐ™์€ ํ…Œ์ŠคํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ํ•จ์ˆ˜๋ช…์„ it์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— Jest์—์„œ๋„ it์„ test ํ•จ์ˆ˜์˜ ๋ณ„์นญ์œผ๋กœ ์ œ๊ณตํ•œ๋‹ค.


### ๐Ÿƒโ€โ™‚๏ธ 4. only/skip
```js
test.only("0๋”ํ•˜๊ธฐ 5์€ 5์•ผ", () => {
expect(fn.add(num, 3)).toBe(5);
});
test.skip("0๋”ํ•˜๊ธฐ 5์€ 5์•ผ", () => {
expect(fn.add(num, 3)).toBe(5);
});

```
- only์™€ skip์€ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ๋””๋ฒ„๊น…ํ•  ๋•Œ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉํ•œ๋‹ค.
- only๋Š” ํ…Œ์ŠคํŠธ ํŒŒ์ผ์•ˆ์— ํ…Œ์ŠคํŠธ ํ•จ์ˆ˜๊ฐ€ ๋งŽ์€๋ฐ ๊ทธ ์ค‘์—์„œ ํ•˜๋‚˜๋งŒ ์‹คํŒจํ–ˆ์„ ๊ฒฝ์šฐ, ๊ทธ ํ•จ์ˆ˜๋งŒ ๋‹จ๋…์œผ๋กœ ์‹คํ–‰ํ•ด๋ณด๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.
- skip์€ only์˜ ๋ฐ˜๋Œ€๋กœ ์ž‘๋™ํ•œ๋‹ค. ์–ด๋–ค ํ•จ์ˆ˜๋งŒ ๋นผ๊ณ  ์‹คํ–‰ํ•ด๋ณด๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.


## ๐Ÿ”– ์‹คํ–‰ ์ˆœ์„œ
```js
beforeAll(() => console.log("๋ฐ– beforeAll")); // 1
beforeEach(() => console.log("๋ฐ– beforeEach")); // 2, 6
afterAll(() => console.log("๋ฐ– afterAll")); // 4, 10
afterEach(() => console.log("๋ฐ– afterEach")); // ๋งˆ์ง€๋ง‰

test("2๋”ํ•˜๊ธฐ 3์€ 5์•ผ", () => {
expect(fn.add(2, 3)).toBe(5); // 3
});

describe("Car ๊ด€๋ จ ์ž‘์—…", () => {
beforeAll(() => console.log("๋ฐ– beforeAll")); // 5
beforeEach(() => console.log("๋ฐ– beforeEach")); // 7
afterAll(() => console.log("๋ฐ– afterAll")); // 9
afterEach(() => console.log("๋ฐ– afterEach")); // ๋งˆ์ง€๋ง‰-1

test("2๋”ํ•˜๊ธฐ 3์€ 5์•ผ", () => {
expect(fn.add(2, 3)).toBe(5); // 8
});
});
```


## ๐Ÿ”– Mockup
### ๐Ÿƒโ€โ™‚๏ธ 1. mockFn.mock.calls
```js
//fnMock.test.js
const mockFn = jest.fn();

function forEachAdd1(arr) {
arr.forEach((num) => {
mockFn(num + 1);
});
}

forEachAdd1([10, 20, 30]);

test("ํ•จ์ˆ˜๋Š” 3๋ฒˆ ํ˜ธ์ถœ๋œ๋‹ค.", () => {
expect(mockFn.mock.calls.length).toBe(3);
});

test("์ „๋‹ฌ๋œ ๊ฐ’์€ 11, 21, 31์ด๋‹ค.", () => {
expect(mockFn.mock.calls[0][0]).toBe(11);
expect(mockFn.mock.calls[1][0]).toBe(21);
expect(mockFn.mock.calls[2][0]).toBe(31);
});

console.log(mockFn.mock.calls); // [[11], [21], [31]]
```
- mockFn.mock.calls์—๋Š” ์ธ์ž๋กœ ๋ฐ›์•„์˜จ ๊ฐ’๋“ค๊ณผ ๊ธธ์ด๋ฅผ ์•Œ ์ˆ˜ ์žˆ๋‹ค.


### ๐Ÿƒโ€โ™‚๏ธ 2. mockFn.mock.results
```js
const mockFn = jest.fn((num) => num + 1);

mockFn(10);
mockFn(20);
mockFn(30);

test("10์—์„œ 1์ฆ๊ฐ€ํ•œ ๊ฐ’์ด ๋ฐ˜ํ™˜๋œ๋‹ค.", () => {
expect(mockFn.mock.results[0].value).toBe(11);
});

test("20์—์„œ 1์ฆ๊ฐ€ํ•œ ๊ฐ’์ด ๋ฐ˜ํ™˜๋œ๋‹ค.", () => {
expect(mockFn.mock.results[1].value).toBe(21);
});

test("30์—์„œ 1์ฆ๊ฐ€ํ•œ ๊ฐ’์ด ๋ฐ˜ํ™˜๋œ๋‹ค.", () => {
expect(mockFn.mock.results[2].value).toBe(31);
});

console.log(mockFn.mock.results);
/*
[
{ type: 'return', value: 11 },
{ type: 'return', value: 21 },
{ type: 'return', value: 31 }
]
*/
```
- mockFn.mock.results๋Š” ๋ฆฌํ„ด๊ฐ’์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.


### ๐Ÿƒโ€โ™‚๏ธ 3. mockReturnValueOnce/mockReturnValue
```js
const mockFn = jest.fn();

mockFn.mockReturnValueOnce(10)
.mockReturnValueOnce(20)
.mockReturnValueOnce(30)
.mockReturnValue(40);

mockFn();
mockFn();
mockFn();
mockFn();

test("dd", () => {
expect("dd").toBe("dd");
});

console.log(mockFn.mock.results);
/*
[
{ type: 'return', value: 10 },
{ type: 'return', value: 20 },
{ type: 'return', value: 30 },
{ type: 'return', value: 40 }
]
*/
```
- mockReturnValueOnce๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด mockFn์ด ์‹คํ–‰๋ ๋•Œ๋งˆ๋‹ค ๋‹ค๋ฅธ ๊ฐ’์„ ๋ฆฌํ„ด์ด ๊ฐ€๋Šฅํ•˜๋‹ค. ๋งˆ์ง€๋ง‰์—๋Š” Once๋ฅผ ์ƒ๋žตํ•œ๋‹ค.


### ๐Ÿƒโ€โ™‚๏ธ 4. mockResolvedValue
```js
const mockFn = jest.fn();

mockFn.mockResolvedValue({ name: "Mike" });

test("๋ฐ›์•„์˜จ ์ด๋ฆ„์€ Mike", () => {
mockFn().then((res) => {
expect(res.name).toBe("Mike");
});
});
```
- mockResolvedValue๋ฅผ ์ด์šฉํ•ด์„œ ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ ํ…Œ์ŠคํŠธํ•ด๋ณผ ์ˆ˜๋„ ์žˆ๋‹ค.


### ๐Ÿƒโ€โ™‚๏ธ 5. mockReturnValue
```js
const fn = require("../fnAsync");

jest.mock("../fnAsync");

fn.createUser.mockReturnValue({ name: "Mike" });

test("์œ ์ €๋ฅผ ๋งŒ๋“ ๋‹ค.", () => {
const user = fn.createUser("Mike");
expect(user.name).toBe("Mike");
});
```
- ๋งŒ์•ฝ db์œ ์ €๋ฅผ ์ƒ์„ฑํ•˜๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•  ๋•Œ ์‹ค์ œ๋กœ db์— ์œ ์ €๊ฐ€ ์ƒ์„ฑ๋˜๋ฉด ์•ˆ๋˜๊ธฐ ๋•Œ๋ฌธ์—, `mockReturnValue`๋ฅผ ์ด์šฉํ•ด์„œ ์‹ค์ œ createUser๊ฐ€ ์‹คํ–‰๋˜์ง€์•Š๊ณ  Mock ํ•จ์ˆ˜๋งŒ ์‹คํ–‰๋˜๊ฒŒ๋” ํ•  ์ˆ˜ ์žˆ๋‹ค.


### ๐Ÿƒโ€โ™‚๏ธ 6. toBeCalled, toBeCalledTimes, toBeCalledWith, lastCalledWith
```js
const mockFn = jest.fn();

mockFn(10, 20);
mockFn();
mockFn(30, 40);

test("ํ•œ๋ฒˆ ์ด์ƒ ํ˜ธ์ถœ?", () => {
expect(mockFn).toBeCalled();
});
test("์ •ํ™•ํžˆ ์„ธ๋ฒˆ ํ˜ธ์ถœ?", () => {
expect(mockFn).toBeCalledTimes(3);
});
test("10์ด๋ž‘ 20 ์ „๋‹ฌ๋ฐ›์€ ํ•จ์ˆ˜ ์žˆ์Œ?", () => {
expect(mockFn).toBeCalledWith(10, 20);
});
test("๋งˆ์ง€๋ง‰ ํ•จ์ˆ˜๋Š” 30์ด๋ž‘ 40๋ฐ›์Œ?", () => {
expect(mockFn).lastCalledWith(30, 40);
});
```
- toBeCalled๋Š” ํ•œ๋ฒˆ ์ด์ƒ ํ˜ธ์ถœ๋ฌ์œผ๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผ๋œ๋‹ค.
- toBeCalledTimes๋Š” ์ •ํ™•ํ•˜๊ฒŒ ํ˜ธ์ถœ ํšŸ์ˆ˜๊ฐ€ ๋งž์œผ๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผ๋œ๋‹ค.
- toBeCalledWith๋Š” ์ธ์ˆ˜๋กœ ์–ด๋–ค ๊ฐ’์„ ๋ฐ›์•˜๋Š”์ง€ ์ฒดํฌํ•œ๋‹ค.
- lastCalledWith๋Š” toBeCalledWith๋Š”์ฒ˜๋Ÿผ ์ธ์ˆ˜๋กœ ์–ด๋–ค ๊ฐ’์„ ๋ฐ›์•˜๋Š”์ง€ ์ฒดํฌํ•˜์ง€๋งŒ ๋งจ ๋งˆ์ง€๋ง‰์œผ๋กœ ํ˜ธ์ถœ ๋œ ํ•จ์ˆ˜๋งŒ ์ฒดํฌํ•œ๋‹ค.


## ๐Ÿ”– React Components
- React Testing Library๋Š” ๋งค์šฐ ์‹ฌํ”Œํ•˜์ง€๋งŒ ๊ฐ•๋ ฅํ•œ API๋ฅผ ๊ฐ–๊ณ  ์žˆ๋‹ค.
- DOM์ปดํฌ๋„ŒํŠธ๋ฅผ ๋žœ๋”๋งํ•ด์ฃผ๋Š” render() ํ•จ์ˆ˜์™€, ํŠน์ • ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œ์ผœ์ฃผ๋Š” fireEvent ๊ฐ์ฒด, ๊ทธ๋ฆฌ๊ณ  DOM์—์„œ ํŠน์ • ์˜์—ญ์„ ์„ ํƒํ•˜๊ธฐ ์œ„ํ•œ ๋‹ค์–‘ํ•œ ์ฟผ๋ฆฌ ํ•จ์ˆ˜๋“ค์ด ์กด์žฌํ•œ๋‹ค.

```js
import { render, fireEvent, screen } from "@testing-library/react";
```
- `@testing-library/react` ๋ชจ๋“ˆ๋กœ ๋ถ€ํ„ฐ ๋ฐ”๋กœ import๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.


### ๐Ÿƒโ€โ™‚๏ธ 1. toBeInTheDocument()
```js
const user = {
name: "Tom",
age: 27,
};

test("Hello ๋ผ๋Š” ๊ธ€์ž๊ฐ€ ํฌํ•จ๋˜๋Š”๊ฐ€?", () => {
render();
const helloEl = screen.getByText(/Hello/i);
expect(helloEl).toBeInTheDocument();
});
```
- getByText๋Š” ํ…์ŠคํŠธ๋ฅผ ๊ฒ€์‚ฌํ•œ๋‹ค.
- toBeInTheDocument๋Š” ๊ฒ€์‚ฌํ•˜๋ ค๋Š” ์š”์†Œ๊ฐ€ ๋ฌธ์„œ์— ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•œ ๋ฉ”์„œ๋“œ์ด๋‹ค.


### ๐Ÿƒโ€โ™‚๏ธ 2. toMatchSnapshot
```js
const user = {
name: "Tom",
age: 27,
};

const user2 = {
age: 30,
};

test("snapshot: name์žˆ์Œ", () => {
const el = render();
expect(el).toMatchSnapshot();
});

test("snapshot: name์—†์Œ", () => {
const el = render();
expect(el).toMatchSnapshot();
});
```
- ์Šค๋ƒ…์ƒท ํ…Œ์ŠคํŒ…(Snapshot testing)์ด๋ž€ ์–ด๋–ค ๊ธฐ๋Šฅ์˜ ์˜ˆ์ƒ ๊ฒฐ๊ณผ๋ฅผ ๋ฏธ๋ฆฌ ์ •ํ™•ํžˆ ํฌ์ฐฉํ•ด๋‘๊ณ  ์‹ค์ œ ๊ฒฐ๊ณผ์— ๋น„๊ตํ•˜๋Š” ํ…Œ์ŠคํŠธ ๊ธฐ๋ฒ•์ด๋‹ค.
- ํ…Œ์ŠคํŠธ ๋Œ€์ƒ ๊ธฐ๋Šฅ์˜ ๊ตฌํ˜„์ด ๋ณ€๊ฒฝ๋˜์–ด ์‹ค์ œ ๊ฒฐ๊ณผ๊ฐ€ ์Šค๋ƒ…์ƒท์„ ๋– ๋†“์€ ์˜ˆ์ƒ ๊ฒฐ๊ณผ์™€ ๋‹ฌ๋ผ์งˆ ๊ฒฝ์šฐ ํ•ด๋‹น ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๋Š” ์‹คํŒจํ•˜๊ฒŒ ๋œ๋‹ค.
- ์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ ๋‹ค์‹œ ์ƒˆ๋กœ์šด ์Šค๋ƒ…์ƒท์„ ๋– ์„œ ๊ธฐ์กด ์Šค๋ƒ…์ƒท์„ ๊ต์ฒดํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ์Šค๋ƒ…์ƒท๋„ ํ•จ๊ป˜ ์œ ์ง€๋ณด์ˆ˜๋ฅผ ํ•œ๋‹ค.
- Jest์—์„œ๋Š” ํŒŒ์ผ ์Šค๋ƒ…์ƒท ํ…Œ์ŠคํŒ…์„ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•ด์„œ `toMatchSnapshot()`์ด๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ์ œ๊ณตํ•œ๋‹ค.


### ๐Ÿƒโ€โ™‚๏ธ 3. Mockup
```js
test("์ดˆ ํ‘œ์‹œ", () => {
Date.now = jest.fn(() => 123456789);
const el = render();
expect(el).toMatchSnapshot();
});
```
- ์‹œ๊ฐ„์ฒ˜๋Ÿผ ๋งค๋ฒˆ ๊ฐ’์ด ๋ฐ”๊ปด์„œ ํ…Œ์ŠคํŠธ๋ฅผ ํ•  ๋•Œ๋งˆ๋‹ค ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๋ถ€๋ถ„์€ mockํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด์„œ ๊ณ ์ •๊ฐ’์„ ์ฃผ๋ฉด ๋œ๋‹ค.