msw (Mock Service Worker)

Bin2·2022년 8월 2일

Mock Service Worker

Service Worker API를 사용하여 실제 요청을 가로채는 API 모킹 라이브러리 이다.

FrontEnd 개발 단계에서 백엔드 API가 준비되지 않더라도 실제 API 요청을 구현할 수 있고 테스트를 할 경우에도 유용하게 사용할 수 있다.

Install

npm install msw --save-dev
yarn add msw --dev

Define Mocks

// src/mocks/handlers.js
import { rest } from "msw";

export const handlers = [
  rest.get("http://localhost:3030/scoops", (req, res, ctx) => {
    return res(
      ctx.json([
        { name: "Chocolate", imagePath: "/images/chocolate.png" },
        { name: "Vanilla", imagePath: "/images/vanilla.png" },
      ])
    );
  }),
  rest.get("http://localhost:3030/toppings", (req, res, ctx) => {
    return res(
      ctx.json([
        { name: "Cherries", imagePath: "/images/cherries.png" },
        { name: "M&Ms", imagePath: "/images/m-and-ms.png" },
        { name: "Hot fudge", imagePath: "/images/hot-fudge.png" },
      ])
    );
  }),
  rest.post("http://localhost:3030/order", (req, res, ctx) => {
    return res(ctx.json({ orderNumber: 123455676 }));
    // return res(ctx.status(500));
  }),
];

지정된 endpoint로 요청시 리턴 값을 지정할 수 있다.

Browser

브라우저 환경에서의 요청을 모킹한다.

// src/mocks/browser.js
import { setupWorker } from 'msw'
import { handlers } from './handlers'
// This configures a Service Worker with the given request handlers.
export const worker = setupWorker(...handlers)
// index.jsx
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";

if (process.env.NODE_ENV === 'development') {
  const { worker } = require('./mocks/browser')
  worker.start()
}

const root = ReactDOM.createRoot(
  document.getElementById("root") as HTMLElement
);
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

Node

노드 환경에서의 요청을 모킹한다.

// src/mocks/server.js
import { setupServer } from "msw/node";
import { handlers } from "./handlers";

export const server = setupServer(...handlers);

Test

만약 테스트시 Response 값을 변경하고 싶다면 ?

// src/setUptest.js
import "@testing-library/jest-dom";

import { server } from "./mocks/server";

beforeAll(() => server.listen());


afterEach(() => server.resetHandlers());

afterAll(() => server.close());
test("handles error for scoops and toppings routes", async () => {
  server.resetHandlers(
    rest.get("http://localhost:3030/scoops", (req, res, ctx) =>
      res(ctx.status(500))
    ),
    rest.get("http://localhost:3030/toppings", (req, res, ctx) =>
      res(ctx.status(500))
    )
  );

  render(<OrderEntry setOrderPhase={jest.fn()} />);
  await waitFor(async () => {
    const alerts = await screen.findAllByRole("alert");
    expect(alerts).toHaveLength(2);
  });
});
profile
Developer

0개의 댓글