From 04308484fc9992c30ac1fc0d049fe38f6f6e82b8 Mon Sep 17 00:00:00 2001 From: imukyee Date: Fri, 15 Jul 2022 12:30:53 +0900 Subject: [PATCH 1/2] #35 Post. Mocking using msw --- .../220715.md" | 223 ++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 "\354\235\264\354\234\244\352\262\275/220715.md" diff --git "a/\354\235\264\354\234\244\352\262\275/220715.md" "b/\354\235\264\354\234\244\352\262\275/220715.md" new file mode 100644 index 0000000..3332a76 --- /dev/null +++ "b/\354\235\264\354\234\244\352\262\275/220715.md" @@ -0,0 +1,223 @@ +## Mocking + +외부 서비스에 의존하지 않고 독립적으로 실행이 가능한 단위 테스트를 작성하기 위해서 사용되는 테스팅 기법 + + + +프론트엔드에서 백엔드의 API를 활용해야 하는 것처럼, 백엔드 개발에 종속적이 부분이 있다면 해당 부분이 완성되기 전까지는 프론트엔드의 개발을 진행할 수 없다. **->** **Mocking을 이용!** + + + +기존에는 화면에 필요한 데이터의 상태를 애플리케이션의 내부 로직에 직접 Mocking 해서 필요한 화면에 붙이거나 Mock 서버를 별도로 만들었다. + +그러나, 내부 로직에 직접 붙이는 경우에는, 구현이 쉽지만, 서비스 로직을 수정해야하고, HTTP 메소드와 네트워크의 응답 상태에 따라 각각 대응하기가 쉽지 않음. + +Mock서버를 별도로 만드는 경우에는 서비스 로직을 수정하지 않아도 되지만, 데이터 상태 구현에 비용이나 인력이 더 많이 들게 된다. + +또한 API 응답 상태에 따라 대기, 로딩, 에러 등의 여러가지 구현이 존재하는데, 이런 경우 각 케이스별로 임의의 상태를 만들어 보면서 개발하기 쉽지 않다! + + + +## MSW.js (Mock Service Worker) + +> [msw공식문서](https://mswjs.io/docs/) + +실제 API를 사용하는 것처럼 네트워크 수준에서 Mocking 가능하도록 해주는 라이브러리 + +Service Worker를 통해 HTTP요청을 가로챌 수 있기 때문에, 네트워크 요청을 보냈을 때 모의 응답을 보내줄 수 있다! 따라서 Mock서버를 구축하지 않아도 API를 네트워크 수준에서 Mocking할 수 있다. + + + +![img](https://tech.kakao.com/wp-content/uploads/2022/01/08-3.png) + + + +### 설치 및 설정 + +> Create-React-App 기반으로 REST API 모킹해보기 + +**msw 설치** + +``` +npm install msw --save-dev +# or +yarn add msw --dev +``` + +**mocks 폴더 생성** + +``` +mkdir src/mocks +``` + +**handlers.js** 파일 생성 + +``` +touch src/mocks/handlers.js +``` + +인터셉트한 request에 따라 돌려 줄 mocked응답을 작성해두는 파일이다. + +ex) + +```javascript +// src/mocks/handlers.js +import { rest } from 'msw' + +export const handlers = [ + // Handles a POST /login request + rest.post('/login', null), + + // Handles a GET /user request + rest.get('/user', null), +] +``` + +**msw 초기화** + +``` +npx msw init --save +``` + + 은 프로젝트 starter를 무엇으로 했는지에 따라 확인하고 지정해주면 된다. + +CRA인 경우엔 `public/` + +
+ +**browser.js 파일 생성** + +``` +touch src/mocks/browser.js +``` + +msw에서 제공하는 서비스워커를 가져와서 위에서 작성한 handlers를 인자로 넘겨준다. + +```javascript +// src/mocks/browser.js +import { setupWorker } from 'msw' +import { handlers } from './handlers' // export default로 해줬을 경우 {} 제거 + +// This configures a Service Worker with the given request handlers. +export const worker = setupWorker(...handlers) +``` + +**서비스 워커 실행** + +```javascript +// src/index.js +import React from 'react' +import ReactDOM from 'react-dom' +import App from './App' + +if (process.env.NODE_ENV === 'development') { + const { worker } = require('./mocks/browser') + worker.start() +} + +ReactDOM.render(, document.getElementById('root')) +``` + +개발 환경일 때, browser.js에서 worker를 가져와서 실행하는 코드를 추가한다. + +API에 대해서 모의 응답이 아닌 실제 응답을 원할 때는 이 코드만 지우고 실행하면 된다. + +
+ +**작동 확인** + +컴포넌트에서 **fetch(‘/login’)** 진행 후 react 서버를 열고 콘솔을 확인했을 때 + +**Mocking enabled** 이라고 빨간 글씨가 적혀있다면 정상 작동하고 있는 것. + + + +### **실습** + +| Parameter name | Description | +| :----------------------------------------------- | :--------------------------------------------------------- | +| [`request`](https://mswjs.io/docs/api/request) | Information about the captured request. | +| [`response`](https://mswjs.io/docs/api/response) | Function to create the mocked response. | +| [`context`](https://mswjs.io/docs/api/context) | Context utilities specific to the current request handler. | + +```javascript +// src/mocks/handlers.js +import { rest } from 'msw' + +const handlers = [ + rest.get('/users', (req, res, ctx) => { + return res( + ctx.status(200), + ctx.delay(1000), + ctx.json([ + { + id: 1, + name: 'deer', + age: 20 + }, + { + id: 2, + name: "coco", + age: 20 + }, + { + id: 3, + name: "ddiyong", + age: 20 + } + ] + ) + ) + }), + ] + +export default handlers +``` + +```javascript +// src/MockingTest.js +import { useState } from 'react' + +function MockingTest () { + + const [userData, setUserData] = useState(); + + function getUsersHandler() { + fetch('/users') + .then((res) => { + return res.json() + }) + .then((json) => { + setUserData(json) + }) + } + + return ( +
+ + {userData && + userData.map((user) => ( +
이름 : {user.name} 나이 : {user.age}
+ )) + } +
+ ); +} + +export default MockingTest; + +``` + +**결과 화면** + +![이미지](https://pbs.twimg.com/media/FXqMWleaUAAx7iu?format=png&name=small) + +
+ +**참고 링크들** + +- https://tech.kakao.com/2021/09/29/mocking-fe/ + +- https://han-py.tistory.com/400 + +- https://velog.io/@9rganizedchaos/%E3%81%93%E3%82%8C%E3%81%8C%E3%83%AA%E3%82%A2%E3%82%AF%E3%83%88%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%EF%BC%81-%E3%80%8CMock-Service-Worker%E3%80%8D \ No newline at end of file From d578cf73b76b254db98852e644791d770a4f6bb5 Mon Sep 17 00:00:00 2001 From: imukyee Date: Fri, 15 Jul 2022 20:32:43 +0900 Subject: [PATCH 2/2] #35 Post. video link --- "\354\235\264\354\234\244\352\262\275/220715.md" | 2 ++ 1 file changed, 2 insertions(+) diff --git "a/\354\235\264\354\234\244\352\262\275/220715.md" "b/\354\235\264\354\234\244\352\262\275/220715.md" index 3332a76..f272ade 100644 --- "a/\354\235\264\354\234\244\352\262\275/220715.md" +++ "b/\354\235\264\354\234\244\352\262\275/220715.md" @@ -1,3 +1,5 @@ + + ## Mocking 외부 서비스에 의존하지 않고 독립적으로 실행이 가능한 단위 테스트를 작성하기 위해서 사용되는 테스팅 기법