MSW(Mock Service Worker)

jiny·2022년 9월 12일
0

FE Testing

목록 보기
1/2
post-custom-banner

목차

  • MSW
  • MSW setting
  • MSW를 활용한 간단한 testing

MSW

Mock by intercepting requests on the network level. Seamlessly reuse the same mock definition for testing, development, and debugging.

  • 공식 문서에서의 MSW 정의
  • API Mocking 라이브러리로써, 서버로 향하는 네트워크 요청을 가로채서 모의 응답을 보내주는 역할을 수행 -> Service Worker를 통해 HTTP 요청을 가로챈다.
  • Mock 서버를 구축하지 않아도 API를 네트워크 수준에서 Mocking이 가능하다.

MSW를 사용하는 이유

  • 프로젝트를 하나 진행하게 되면 정적 페이지가 아닌 이상비동기 데이터 작업이 필수로 존재하게 된다.
  • 그럴 경우 백엔드 개발자와 함께 요구사항을 파악하며 API 스펙에 대해 이야기를 하게 된다.
  • API 스펙이 협의가 되면 백엔드 개발자는 API를 설계하고 프론트엔드 개발자는 설계된 API를 통해 데이터 Fetching 작업을 통해 얻은 데이터를 브라우저에 렌더링 시킨다.
  • 하지만 프론트엔드 개발자는 테스팅도 해야하며, 기획자에게 진행 사항을 공유해야하기 때문에 백엔드 개발자를 기다리고 있을 수는 없다.
  • 그렇기 때문에 API가 설계 되기 전에 데이터 작업을 테스팅 하기 위한 도구가 필요한데, 그것이 바로 MSW 이다.

MSW의 방식

MSW가 제공하는 과정은 다음과 같다.

  1. 클라이언트 측에서 서버 측에 요청
  2. Service Worker에선 해당하는 실제 요청을 복사
  3. MSW에게 해당 요청과 일치하는 모의 응답을 제공 받고 이를 브라우저에게 그대로 전달

이러한 과정을 통해, 실제 서버 존재 여부와 상관없이 실제 요청으로 이어지지 않고 예상 할 수 있는 요청에 대해 Mocking이 가능하다.

  • 즉, 서버를 직접 만들 필요 없이 msw 라이브러리를 통해 실제 요청을 가로 챈 후 모의 응답을 브라우저 측에 제공하여 마치 실제 http 통신을 하는 거 같은 경험을 개발자에게 제공한다.

  • 그렇기 때문에, 프론트엔드 개발자는 백엔드 개발자의 API 설계를 기다릴 필요 없이 msw를 통해 데이터 패칭 관련 테스팅을 진행할 수 있다.

MSW settings

npm install msw --save-dev

yarn add msw
  • 터미널에 다음과 같은 명령어로 설치가 가능하다.

handler.ts

import { rest } from 'msw';

export const handlers = [
  rest.get('http://localhost:5000/products', (req, res, ctx) => {
    return res(
      ctx.status(200),
      ctx.json([
        {
          name: 'America',
          imagePath: 'images/america.jpeg',
        },
        {
          name: 'England',
          imagePath: 'images/england.jpeg',
        },
      ])
    );
  })
  • 우선, 브라우저 측에 요청을 보내면 모의 응답을 제공할 handler를 setting 한다.
  • rest를 import한 후 서버에 있는 데이터 요청이기 때문에 get을 사용했다.
  • 인자안에는 url, 콜백 함수가 필요하다.
  • 콜백 함수에는 request, response, context 총 3개의 매개변수가 필요한데, request는 매칭 요청에 대한 정보, response는 모의 응답을 생성하는 기능적 유틸리티, context는 모의 응답의 상태 코드, 헤더, 본문 등을 설정하는데 도움을 준다.
  • 중괄호 안에는 http의 status나 필요한 데이터를 return 한다.

browser.ts

import { setupWorker } from 'msw';
import { handlers } from './handlers';

export const worker = setupWorker(...handlers);
  • 브라우저에서도 확인하고 싶어 만든 파일이다.
  • setupWorker는 브라우저 환경에서 mocking 하도록 제공하는 함수이다.
  • 인자안에는 handler를 스프레드 문법으로 쓰면 된다.

server.ts

import { setupServer } from 'msw/node';
import { handlers } from './handlers';

export const server = setupServer(...handlers);
  • jest로 테스팅할 땐 node 환경에서 돌아가기 때문에 server 파일을 만들었다.
  • 구성은 browser와 거의 동일하며, setupServer 함수는 msw/node에서 제공한다.
npx msw init public/ --save
  • 다음과 같은 명령어를 통해 생성한 서비스 워커를 브라우저에 등록한다.

  • 다음과 같은 파일이 생성되었으면 올바르게 입력한 것이다.

index.tsx

if (process.env.NODE_ENV === 'development') {
  worker.start();
}
  • 브라우저에서 service worker가 잘 동작하는 지 체크하기 위해 추가해준다.

  • mocking enabled가 뜬다면 잘 연결 된 것

MSW를 활용한 testing

setUpTest.ts

import { server } from './server';
import '@testing-library/jest-dom';

export function mockServer() {
  beforeAll(() => server.listen());
  afterEach(() => server.restoreHandlers());
  afterAll(() => server.close());
}
  • 어떤 test 파일에서는 mocking하는 작업이 필요하지 않을 수 있다.
  • 그래서 setUpTest.ts를 통해 필요한 test 파일에서만 testing할 수 있도록 진행
  • jest-dom을 import 하여 다음과 같은 코드를 작성

Product.test.ts

import { render, screen } from '@testing-library/react';
import OrderComponent from '../../../components/OrderPage/OrderComponent';
import { mockServer } from '../../../utils/mocks/setUpTest';

describe('Product component test', () => {
  mockServer();
  test('check rendering image from server', async () => {
    render(OrderComponent());
    const productImages = await screen.findAllByRole('img', {
      name: /product/i,
    });
    expect(productImages).toHaveLength(2);
  });
});
  • 이미지를 서버로 부터 받아오는 test 작업을 테스팅
  • msw를 켜는 mockServer 함수를 불러 와서 테스팅을 진행하는 작업

실행 결과

  • 잘 실행 된 것을 확인

Mock server를 코드에서 빼버리면 어떻게 될까?

  • 혹시나 response가 없을 수도 있을 거 같아 mockServer()를 테스팅 코드에서 빼보았는데 axiosError가 되어 fail이 된 것을 확인 할 수 있었다.

레퍼런스

msw 공식 문서

https://mswjs.io/

Mocking으로 생산성까지 챙기는 FE 개발

https://tech.kakao.com/2021/09/29/mocking-fe/

post-custom-banner

0개의 댓글