> For the complete documentation index, see [llms.txt](https://taewoongs-organization.gitbook.io/jtwjs-dev-wiki/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://taewoongs-organization.gitbook.io/jtwjs-dev-wiki/dev_note/testing/undefined-6/msw.md).

# MSW

## Mock Service Worker

> 네트워크 계층의 목 객체를 만드는 라이브러리

* 웹 API 요청을 가로채서 임의의 값으로 만든 응답으로 대체
  * 생성된 요청의 `headers` , `query` 의 세부 내용을 검증 또한 가능
* 웹 API 서버를 실행하지 않아도 응답 재현 가능
* 웹 API 요청을 가로채려면 요청 핸들러를 만들어야한다.
* 브라우저나 서버 등 어디에서 생성된 요청인지 관계없이 요청을 가로챌 수 있어 BFF를 포함한 다양한 프론트엔드 테스트 환경에서 활용 가능&#x20;

```typescript
import { setupWorker, rest } from 'msw';

const worker = setupWorker(
  rest.post("/login", async (req, res, ctx) => {
    const { username } = await req.json();
    return res(
      ctx.json({ 
       username,
       firstName: "John",
      })
    )
  })
);
worker.start();

// setupServer 
// server.ts
import { setupServer } from "msw/node";

import handlers from "./handlers";

const server = setupServer(...handlers);

export default server;

// handlers.ts
import { rest } from "msw";

import * as fixtures from "@/fixtures";

const handlers = [
  rest.get("/categories", (req, res, ctx) =>
    res(ctx.json({ categories: fixtures.categories }))
  ),
  rest.get("/products", (req, res, ctx) => {
    const categoryId = req.url.searchParams.get("categoryId");

    if (categoryId) {
      return res(
        ctx.json({
          products: fixtures.products.filter(
            (product) => product.category.id === (categoryId as string)
          ),
        })
      );
    }
    return res(ctx.json({ products: fixtures.products }));
  })]
```

{% hint style="info" %}
setupWorker와 setupServer는 무엇이 다른고?

* **Node.js 환경에서 서버 요청 모킹**: `setupServer`
* **브라우저 환경에서 클라이언트 요청 모킹**: `setupWorker`

jest는 node.js 환경에서 동작하므로 테스트 환경에선 setupServer를 사용
{% endhint %}

### Jest용 세팅

* `setupTests.ts` 에서 테스트의 설정을 글로벌 관리

```typescript
// eslint-disable-next-line import/no-extraneous-dependencies
import "@testing-library/jest-dom";
import "whatwg-fetch";

import server from "./mocks/server";

// 테스트 전 목킹한 msw 서버와 연결
beforeAll(() => server.listen({ onUnhandledRequest: "error" }));
// 각 테스트 후 다른 테스트에 영향을 미치지 않기 위해 연결된 핸들러 초기화
afterEach(() => server.resetHandlers());
// 모든 테스트 완료 후 연결 끊기
afterAll(() => server.close());
```

{% hint style="danger" %}
테스트 환경인 jsdom에 Fetch API가 적용되지 않았기 때문에 Fetch API를 사용하는 코드가 테스트 대상에 포함되면 테스트를 실패한다.

Fetch API의 폴리필인 `whatwg-fetch` 를 설치해 모든 테스트에 적용하도록 설정 파일에 import&#x20;
{% endhint %}
