πŸ’œVitest | MSW μ‚¬μš©ν•˜μ—¬ API μš”μ²­ mocking

μ›μ˜Β·2024λ…„ 1μ›” 22일
1
post-thumbnail

⚑MSW(mock-service-worker)

  • μ„œλ²„μ˜ 응닡 값을 λͺ¨μ˜ μ‘λ‹΅μœΌλ‘œ 보냄
  • API μš”μ²­μ΄ λ°œμƒν•  λ•Œ μ„œλ²„λ‘œ μ „λ‹¬λ˜λŠ” μš”μ²­μ„ κ°€λ‘œμ±„κ³  그에 λŒ€ν•œ λͺ¨μ˜ 응닡을 λ³΄λ‚΄κ²Œ μ œμ–΄

⚑기λŠ₯ ν…ŒμŠ€νŠΈμ—μ„œ μ‚¬μš© 이유

  • κΈ°λŠ₯ν…ŒμŠ€νŠΈλŠ” μ‹€μ œ ν™˜κ²½μ—μ„œ μˆ˜ν–‰ν•˜λŠ” ν…ŒμŠ€νŠΈ(end-to-end)κ°€ μ•„λ‹ˆλΌμ„œ 보톡 μ„œλ²„λ₯Ό 끼고 ν•˜μ§€ μ•ŠμŒ
  • ν…ŒμŠ€νŠΈ μ€‘μ—λŠ” μ‹€μ œ λ„€νŠΈμ›Œν¬ ν˜ΈμΆœμ„ 막고, μ„œλ²„ 응닡(μ˜΅μ…˜)에 λ”°λ₯Έ ν…ŒμŠ€νŠΈ 쑰건 μ„€μ •

❓MSW μ‚¬μš©ν•˜μ§€ μ•Šκ³  axiosλ₯Ό λ°”λ‘œ mockingν•˜λ©΄?

  • λ™μ‹œμ— 두 가지λ₯Ό μš”μ²­ν•˜λŠ” ν•œ μ»΄ν¬λ„ŒνŠΈμ—μ„œ axiosλ₯Ό mockingν•˜λ©΄, λ°˜ν™˜κ°’μœΌλ‘œλŠ” 이λ₯Ό κ΄€λ¦¬ν•˜κΈ° μ–΄λ ΅κ³  λΆˆμ•ˆμ •
  • νŽ˜μ΄μ§€λ₯Ό λ‹€μ‹œ μ •λ ¬ν•˜λ©΄ λͺ¨μ˜ ν™”λ©΄μ—μ„œ λ°˜ν™˜κ°’μ˜ μˆœμ„œκ°€ 잘λͺ»λ˜μ–΄ ν…ŒμŠ€νŠΈ μ‹€νŒ¨ν•  수 있음
  • MSW ν•Έλ“€λŸ¬ ν•¨μˆ˜λ‘œ μš”μ²­μ˜ νŒŒλΌλ―Έν„° 등에 따라 λ‹€λ₯Έ κ°’ λ°˜ν™˜ κ°€λŠ₯
  • μΏ ν‚€, 이진 응닡(예: 이미지) λ“±μ˜ μš”μ²­ 처리 κ°€λŠ₯
    μš”μ•½: κ°„λ‹¨ν•œ μ•±μ—μ„œλŠ” λͺ¨ν‚Ήμ΄ κ°€λŠ₯ν•˜μ§€λ§Œ 더 λ³΅μž‘ν•œ μ•±μ—μ„œλŠ” MSW둜 λ‹€μ–‘ν•œ 도ꡬλ₯Ό μ΄μš©ν•˜λŠ” 것이 μ’‹μŒ

βš‘μ‚¬μš© 방법

1. μ„€μΉ˜

yarn add msw

2. ν•Έλ“€λŸ¬ 파일 생성

  • νŠΉμ • URL, κ²½λ‘œμ— μ–΄λ–€ 응닡이 μ™”λŠ”μ§€λ₯Ό νŒŒμ•…
  • ν˜•μ‹
  • REST API 호좜 μ‹œ http ν•Έλ“€λŸ¬ νƒ€μž… μ‚¬μš©
// src.mocks.handler.ts 생성
import { http, HttpResponse } from "msw";

export const handlers = [
http.get("http://localhost:3030/scoops", async () => {
    return HttpResponse.json([
      { name: "Chocolate", imagePath: "/images/chocolate.png" },
      { name: "Vanilla", imagePath: "/images/vanilla.png" },
    ]);
  })
]
  • HttpResponse.json() : 응닡 객체 λ°˜ν™˜μ‹œ 일반적으둜 κ°μ‹Έμ£ΌλŠ” λ©”μ„œλ“œ
  • request, parameter ν™œμš©ν•΄ 응닡값 가곡 κ°€λŠ₯

3. μš”μ²­μ„ μ²˜λ¦¬ν•  ν…ŒμŠ€νŠΈ μ„œλ²„ 파일 생성

  • ν…ŒμŠ€νŠΈ μˆ˜ν–‰ μ€‘μ—λŠ” μ„œλ²„κ°€ κ³„μ†ν•΄μ„œ λ¦¬μŠ€λ‹ν•˜λ©΄μ„œ μ‹€μ œλ‘œ λ„€νŠΈμ›Œν¬λ₯Ό 탔을 호좜 κ°€λ‘œμ±„μ•Ό 함(setupTests.js)
  • ν•œ ν…ŒμŠ€νŠΈ 끝날 λ•Œλ§ˆλ‹€ μ„œλ²„ ν•Έλ“€λŸ¬ 리셋
// src/mocks/server.ts 생성
import { setupServer } from 'msw/node'
import { handlers } from './handlers'
 
export const server = setupServer(...handlers)

4. setup μ„€μ •

// vitest.setup.ts μΆ”κ°€
import { beforeAll, afterEach, afterAll } from 'vitest'
import { server } from './src/mocks/node'
 
beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
afterAll(() => server.close())

βš‘ν…ŒμŠ€νŠΈ μ½”λ“œ

  • νŽ˜μ΄μ§€μ—μ„œ λΉ„λ™κΈ°μ‹μœΌλ‘œ λ‚˜νƒ€λ‚˜λŠ” μš”μ†Œλ₯Ό ν…ŒμŠ€νŠΈν•˜κΈ° μœ„ν•΄μ„œλŠ” await , findBy ν•„μˆ˜ μ‚¬μš©(getBy μ‚¬μš© X)
const images = await screen.findAllByRole("img", { name: /test$/i });
expect(images).toHaveLength(3);
profile
ν™”μ΄νŒ…~~^ㅁ^/

0개의 λŒ“κΈ€