안녕하세요. J4J입니다.
이번 포스팅은 MSW API Mocking 하기 마지막인 Cypress에서 사용하는 방법에 대해 적어보는 시간을 가져보려고 합니다.
이전 글
[React] MSW로 API Mocking 하기 (1) - MSW란?
[React] MSW로 API Mocking 하기 (2) - Browser 환경에서 사용하기
[React] MSW로 API Mocking 하기 (3) - Node 환경에서 사용하기
[React] MSW로 API Mocking 하기 (4) - Storybook에서 사용하기
설정 방법
Cypress에 MSW를 적용하기 위해서는 Cypress를 사용할 수 있는 환경과 MSW Browser 환경 설정이 되어 있어야 합니다.
만약 각 환경 구축이 필요하신 경우 다음 글들을 참고해 주시면 됩니다.
추가 참고사항으로 만약 Browser 환경에 있는 소스 코드를 그대로 적용시켰다면 index나 main 파일에 다음과 같이 worker 등록을 위한 코드가 사용되고 있을 겁니다.
해당 코드는 Cypress 테스트에 영향을 줄 수 있다는 것을 인지해주시길 바랍니다.
if(process.env.NODE_ENV === 'development') { // 개발에서만 msw 동작
worker.start();
}
[ 1. cypress base url 설정 ]
Cypress가 올바르게 설정되어 사용하고 있다면 최상위 경로에 cypress.config.ts 파일이 있는 것을 확인할 수 있습니다.
해당 파일에 테스트 할 로컬 서버가 실행되었을 때 잡히는 경로를 baseUrl로 다음과 같이 설정을 해주시면 됩니다.
해당 설정은 Browser 환경에서 MSW 설정을 할 때 생성했던 public 폴더 내부에 있는 mockServiceWorker의 동작을 위해서 하는 것으로 만약 설정하지 않는다면 Cypress에서 mockServiceWorker를 올바르게 찾아가지 못하게 됩니다.
import { defineConfig } from "cypress";
export default defineConfig({
e2e: {
baseUrl: 'http://localhost:5173' // mockServiceWorker 사용을 위한 서버 실행 경로 baseUrl 설정
},
});
[ 2. worker 등록 ]
Browser 환경을 설정할 때 생성해 둔 worker를 Cypress를 이용한 테스트를 할 때 사용될 수 있도록 등록해 보겠습니다.
이 또한 Cypress가 올바르게 설정되어 사용하고 있다면 cypress/support 경로에 commands.ts 파일이 있는 것을 확인할 수 있습니다.
해당 파일은 Cypress에 전역으로 사용할 수 있는 custom command를 등록하는 등의 목적으로 활용되는데 이곳에 다음과 같이 설정을 한다면 테스트를 할 때 기존에 작성해 둔 worker를 그대로 활용할 수 있도록 도와줍니다.
/// <reference types="cypress" />
import { worker } from '../../src/mocks/browser';
// 테스트를 시작하기 전 worker 동작
before(() => {
worker.start();
})
// 테스트가 끝날 때 마다 handler reset 처리 (다른 테스트에 영향을 주지 않기 위해)
Cypress.on('test:before:run', () => {
worker.resetHandlers()
})
테스트
위와 같이 설정을 모두 마쳤다면 테스트를 진행해 보겠습니다.
위에서 정의했던 handler를 그대로 활용하는 페이지와 해당 페이지를 cypress를 이용하여 테스트하는 소스를 다음과 같이 작성해 보겠습니다.
// src/App.tsx
import axios from "axios";
import { useEffect, useState } from "react";
export default function App() {
const [personNames, setPersonNames] = useState<string[]>([]);
async function apiGetNames() {
const res = await axios.get('/get-names');
if(res.data) {
setPersonNames(res.data);
}
}
useEffect(() => {
apiGetNames();
}, [])
return (
<div>
<div>
<h2>사람들의 이름을 호출해보겠습니다 !</h2>
</div>
<div>
{personNames.map((personName, index) => (
<p key={personName} data-cy='person-name-text'>{index+1}번째 이름은 {personName}입니다.</p>
))}
</div>
</div>
)
}
// cypress/e2e/App.cy.ts
describe('app test', () => {
it('/get-names api msw mocking 처리 확인 테스트 ', () => {
cy.visit('/');
cy.get('[data-cy=person-name-text]').should('have.length', 4);
});
});
그리고 cypress가 동작되는 브라우저에 접속하여 확인해 보면 다음과 같이 mocking 처리가 된 API가 호출되어 테스트가 올바르게 수행된 것을 볼 수 있습니다.
상황 별 다른 Mocking 처리 (Override)
이전 글들에서도 동일한 제목의 내용들을 계속 다뤘습니다.
cypress에서도 해당 설정을 동일하게 적용해 볼 수 있습니다.
만약 cypress를 사용하다가 작성된 테스트마다 동일한 API에 대해 다른 mocking 결과가 필요한 경우가 발생한다면 다음과 같이 설정해주시면 됩니다.
[ 1. override를 위한 custom command 추가 ]
위에서 worker를 등록했던 commands.ts 파일에 handler를 추가할 수 있는 custom command를 다음과 같이 추가해 주시면 됩니다.
/// <reference types="cypress" />
import { RequestHandler } from 'msw';
import { worker } from '../../src/mocks/browser';
declare global {
namespace Cypress {
interface Chainable {
workerUse(...handlers: RequestHandler[]): void
}
}
}
// cypress command로 worker에 추가 handler를 등록하기 위해 custom command 등록
Cypress.Commands.add('workerUse', (...handlers: RequestHandler[]) => {
worker.use(...handlers)
})
[ 2. 테스트에 override handler 정의 ]
custom command를 위와 같이 만들었다면 테스트를 작성할 때 다음과 같이 handler 정의 및 추가를 하여 테스트 결과에 활용해 볼 수 있습니다.
import { rest } from "msw";
describe('app test', () => {
it('/get-names api msw mocking 처리 확인 테스트 ', () => {
cy.workerUse(
// GET method인 /get-names를 해당 페이지에서만 따로 활용
rest.get('/get-names', (req, res, ctx) => {
const names = ['app-jimi', 'app-john', 'app-scott', 'app-queen']
return res(
ctx.status(200),
ctx.json(names),
)
})
)
cy.visit('/');
cy.get('[data-cy=person-name-text]').should('have.length', 4);
});
});
[ 3. 테스트 ]
설정하고 테스트를 해보면 override한 handler 결과가 다음과 같이 활용되는 것을 확인할 수 있습니다.
이상으로 MSW API Mocking 하기 마지막인 Cypress에서 사용하는 방법에 대해 간단하게 알아보는 시간이었습니다.
읽어주셔서 감사합니다.
'SPA > React' 카테고리의 다른 글
[React] Jest 이벤트 처리 비교, fireEvent vs userEvent (2) | 2023.11.02 |
---|---|
[React] Vite 타입 스크립트 프로젝트에 ESLint / Prettier 설정하기 (2) | 2023.10.31 |
[React] MSW로 API Mocking 하기 (4) - Storybook에서 사용하기 (1) | 2023.10.16 |
[React] MSW로 API Mocking 하기 (3) - Node 환경에서 사용하기 (0) | 2023.10.11 |
[React] MSW로 API Mocking 하기 (2) - Browser 환경에서 사용하기 (1) | 2023.10.09 |
댓글