๋จ์ ํ ์คํธ ๋์ ์ ์ ํ๊ธฐ
์ ๋ฒ์๊ฐ์ ๋ณด์๋ ๋จ์ํ
์คํธ๊ฐ ๋ฌด์์ธ๊ฐ ๋์๋ณด์๋ฉด, ๋ค๋ฅธ ์ปดํฌ๋ํธ์์ ์ํธ์์ฉ์ด ์๋ ๋จ์ผ ์ปดํฌ๋ํธ๋ฅผ, ๊ทธ ์ปดํฌ๋ํธ๊ฐ ์์๋๋ก ๋์ํ๋์ง ํ์ธํ๋ ํ
์คํธ์ด๋ค.
๊ทธ๋์ Atomic ์ปดํฌ๋ํธ๋ผ๊ณ ๋ถ๋ฆฌ๋ ๊ฒ๋ค์ด ๋จ์ํ
์คํธ์ ์ฃผ ๋์์ด๋ผ๊ณ ํ๋ค.
ํ์ง๋ง ๋ฐ๋ฉด ๋ ๋๋ฌด ๋จ์ํ ๊ฒฝ์ฐ(๋จ์ํ ui ๋ ๋๋ง, ๊ฐ๋จํ ๋ก์ง)์๋ ์ผ์ผ์ด ๋จ์ํ ์คํธ๋ฅผ ๊ฑฐ์น ํ์ ์์ด ๋ค๋ฅธ ์ปดํฌ๋ํธ๋ค๊ณผ ํจ๊ป (์์ ์ปดํฌ๋ํธ์์) ํตํฉํ ์คํธ์์ ๊ฒ์ฆํ๋๊ฒ์ผ๋ก๋ ์ถฉ๋ถํ๋ค.
๋ฆฌ์กํธ ํ , ์ ํธํจ์
์ปดํฌ๋ํธ ์ธ์๋ ๋ฆฌ์กํธ ํ ๊ณผ ์ ํธ ํจ์๋ ๋จ์ ํ ์คํธ์ ๋์์ด ๋๋ค. (๋จ์ ํ ์คํธ๋ก ๊ฒ์ฆํ๊ธฐ ๋งค์ฐ ์ ํฉํ๋ค)
์ ํธ ํจ์๋ ๋ณดํต ์ฌ๋ฌ ์ปดํฌ๋ํธ์์ ๊ณตํต์ ์ผ๋ก ์ฌ์ฉ๋๋ ํจ์๋ค์ด๊ณ ๋ค์๊ณผ ๊ฐ์ ํน์ง๋ค์ ๊ฐ์ง๊ณ ์๋ค :
- ์์ ํจ์ : ํจ์ ์ธ๋ถ์ ์ํ๋ฅผ ๋ณ๊ฒฝํ๋ ๋ฑ, ์ธ๋ถ์ ์ํธ์ญ์ฉ ํ์ง ์๋ ํจ์. (๋ถ๋ณ ์์ ๋จ์ ์ฐธ์กฐ๋ ์ ์ธ)
- UI ๋ก์ง๊ณผ ๋ฌด๊ด
- ๋น์ฆ๋์ค ๋ก์ง : ๊ณ์ฐ, ๋ณํ, ๊ฒ์ฆ ๋ฑ์ ์์ํ ๋ก์ง
๋ชจ๋ ๋ชจํน
shopping-mall-unit-test
๋ธ๋์น์์ EmptyNotice
์ NotFoundPage
,ErrorPage
์ปดํฌ๋ํธ๋ค์ ๋จ์ ํ
์คํธ ํ๋ค.
EmptyNotice
: ์ฅ๋ฐ๊ตฌ๋๊ฐ ๋น์ด์๋ ์ํ์์ ์ฅ๋ฐ๊ตฌ๋ ํ์ด์ง๋ก ์ด๋์์ ์ฅ๋ฐ๊ตฌ๋๊ฐ ๋น์ด์๋ค๊ณ ๋ณด์ฌ์ฃผ๋ ์ปดํฌ๋ํธ- ์ด ์ปดํฌ๋ํธ๋ ์ฌ์ค ์ฌ๋ฌ ์ปดํฌ๋ํธ๋ค์ด ์กฐํฉ๋์ด ์ด๋ฃจ์ด์ง ์ปดํฌ๋ํธ์์๋ ๋ถ๊ตฌํ๊ณ ํ์ผ๋ก ์ด๋ํ๋ค๋ ํ๋์ ๊ธฐ๋ฅ๋ง ๊ฐ์ง๊ณ ์๊ธฐ ๋๋ฌธ์ ๋ ๋ฆฝ์ ์ธ ์ปดํฌ๋ํธ๋ผ๊ณ ๋ณผ ์ ์๋ค.
NotFoundPage
: ์ฌ์ฉ์๊ฐ ์๋ชป๋ ๊ฒฝ๋ก๋ก ์ด๋ํ์ ๋ ๋ณด์ฌ์ฃผ๋ ํ์ด์งErrorPage
: ์์ํ์ง ๋ชปํ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ ๋ ๋ณด์ฌ์ฃผ๋ ํ์ด์ง- ๋ ์๋ฌ ํ์ด์ง ๋ชจ๋ ํ์ด์ง ๋จ์์ ํฐ ์ปดํฌ๋ํธ์์๋ ๋ถ๊ตฌํ๊ณ ๊ต์ฅํ ๋จ์ํ ๊ตฌ์ฑ ์์๋ฅผ ๊ฐ์ง๊ณ ์๊ณ ๋ง์ฐฌ๊ฐ์ง๋ก '๋ค๋ก ์ด๋'๊ณผ ๊ฐ์ ๊ฐ๋จํ ๊ธฐ๋ฅ๋ง ๊ฐ์ง๊ณ ์๊ธฐ ๋๋ฌธ์ ๋จ์ ํ ์คํธ๋ก ๊ฒ์ฆํ ์ ์๋ค.
๊ทธ๋ฐ๋ฐ ์ ์ธ ์ปดํฌ๋ํธ ๋ชจ๋ react-router-dom
์ useNavigate()
ํ
์ ๊ฐ์ ธ์ ์ฌ์ฉํ๊ณ ์๋ค. (์ฆ react-router-dom
์ ์์กด์ฑ์ ๊ฐ์ง๊ณ ์๋ค.)
์ด ์ปดํฌ๋ํธ๋ค์ ๋จ์ ํ
์คํธ ํ ๋๋ ํด๋น ๊ธฐ๋ฅ์ ์ ๋๋ก ํธ์ถํ๋์ง๋ง ๊ฒ์ฆํ๋ฉด ๋๋ค. (์ธ๋ถ ๋ชจ๋์ ๊ฒ์ฆ์ ํด๋น ๋ชจ๋ ์์ฒด์์ ํ
์คํธ๋ฅผ ํตํด ๊ฒ์ฆํ ์ผ์ด์ง ์ฐธ์กฐํ๊ณ ์๋ ์ฌ๊ธฐ์ ํ ์ผ์ ์๋)
๊ทธ๋ฆฌ๊ณ ์ด ์ธ๋ถ ๋ชจ๋์ ํน์ ๊ธฐ๋ฅ์ ์ ๋๋ก ํธ์ถํ๋์ง ์์๋ณด๊ธฐ ์ํด ๋ชจํน์ด๋ผ๋ ๊ฒ์ ํ๋ค.
๋ชจํน : ์ค์ ๋ชจ๋,๊ฐ์ฒด์ ๋์ผํ ๋์์ ํ๋๋ก ๋ง๋ ๋ชจ์ ๋ชจ๋,๊ฐ์ฒด๋ก ์ค์ ๋ฅผ ๋์ฒดํ๋ ๊ฒ.
- ๋ชจํน์ ํตํด ์ฐ๋ฆฌ๋ ์ธ๋ถ ๋ชจ๋๊ณผ ๊ฒ์ฆํ ๋ชจ๋์ ๋ถ๋ฆฌํด์ ํ์ํ ๊ฒ์ฆ๋ง ์งํํ ์ ์๋ค.
- ๊ทธ๋ฌ๋ ์ค์ ๋ชจ๋๊ณผ ์์ ํ ๋์ผํ ๋ชจ์ ๊ฐ์ฒด๋ฅผ ๊ตฌํํ๋ ๊ฒ์ ํฐ ๋น์ฉ์ด ๋๋ ์์ ์ด๋ฉฐ, (์ ํํ ๋ฌด์จ๋ป์ผ๊น?)
- ๋ชจ์ ๊ฐ์ฒด๋ฅผ ๋จ์ฉํ๋ ๊ฒ์ ํ ์คํธ ์ ๋ขฐ์ฑ์ ๋ฎ์ถ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ณ๋๋ค.
const navigateFn = vi.fn();
vi.mock('react-router-dom', async () => {
const original = await vi.importActual('react-router-dom');
return { ...original, useNavigate: () => navigateFn };
});
it('Home์ผ๋ก ์ด๋ ๋ฒํผ ํด๋ฆญ์ ํ ๊ฒฝ๋ก๋ก ์ด๋ํ๋ navigate๊ฐ ์คํ๋๋ค', async () => {
const { user } = await render(<NotFoundPage />);
const button = await screen.getByRole('button', { name: 'Home์ผ๋ก ์ด๋' });
await user.click(button);
expect(navigateFn).toHaveBeenNthCalledWith(1, '/', { replace: true });
});
vi.mock()
ํจ์๋ฅผ ํตํด react-router-dom
์ ๋ชจํน์ ๋ง๋ ๋ค.
๊ทธ๋ฌ๋ฉด <NotFoundPage />
์ปดํฌ๋ํธ๊ฐ ๋ถ๋ฌ์ค๋ ํด๋น ๋ชจ๋์ ์ง์ง ๋ชจ๋์ด ์๋ ์ฌ๊ธฐ์ ๋ง๋ค์ด์ง ๋ชจํน์ด ๋๋ค.
๊ทธ ์ปดํฌ๋ํธ์์ useNavigate()
๋ฅผ ํธ์ถํ ๋ค์๊ณผ ๊ฐ์ด ํธ์ถํ ๋
const handleClickNavigateHomeButton = () => {
navigate(pageRoutes.main, { replace: true });
};
return(
...
<button onClick={handleClickNavigateHomeButton}>Home์ผ๋ก ์ด๋</button>
)
์ค์ ๋ก ํธ์ถ๋๋ ๊ฒ์ ๋ชจํน์ ๋ฃ์๋ navigateFn
์คํ์ด ํจ์๋ค.
๊ทธ๋์ expect()
๋งค์ฒ๋ก useNavigate()
ํจ์๋ฅผ ํธ์ถํ๋ฉด์ ์ด๋ค ์ธ์๋ฅผ ๋ฃ์๋์ง ("/", {replace : true}
)ํ์ธํ ์ ์๊ฒ ๋๋ค.
๋ชจํน ์ด๊ธฐํ
์์์ useNavigate()
์ react-router-dom
๋ชจ๋์ ๋ชจํนํ๋ค.
๊ทธ๋ฐ๋ฐ ์ด ๋ชจํน์ด ๋ค๋ฅธ ํ
์คํธ์ ์ํฅ์ ์ค ์ ์๋ ๊ฒฝ์ฐ(๋ค๋ฅธ ํ
์คํธ์์๋ ๋ค๋ฅธ ๋ฐฉ์์ผ๋ก ๋ชจํน์ ํด์ผํ๋ค๋๊ฐ)๋ฅผ ์ํด ํ
์คํธ ์ํ ํ์๋ ๋ชจํน์ ์ด๊ธฐํํ๋๊ฒ์ด ์ข๋ค.
//setupTests.js
...
beforeAll(() => {
server.listen();
});
afterEach(() => {
server.resetHandlers();
vi.clearAllMocks();
});
afterAll(() => {
vi.resetAllMocks();
server.close();
});
...
clearAllMocks()
:
- ๋ชจํน๋ ๋ชจ์ ๊ฐ์ฒด ํธ์ถ์ ๋ํ ํ์คํ ๋ฆฌ๋ฅผ ์ด๊ธฐํ
- ํ์คํ ๋ฆฌ๊ฐ ์ด๊ธฐํ๋์ง ์๊ณ ๊ณ์ ์์ด๋ฉด ํธ์ถ ํ์๋ ์ธ์๊ฐ ๋ณ๊ฒฝ๋์ด ๋ค๋ฅธ ํ ์คํธ์ ์ํฅ์ ์ค ์ ์๋ค.
- ๋ชจํน๋ ๋ชจ๋์ ๊ตฌํ์ ์ด๊ธฐํ ํ์ง๋ ์๋๋ค (๋ชจํน๋ ์ํ๋ก ์ ์ง)
resetAllMocks()
:
- ๋ชจํน๋ ๋ชจ๋์ ๊ตฌํ์ ์ด๊ธฐํ