API 호출을 조롱하거나 스터빙하는 단위 테스트를 작성하는 것은 부담스러울 수 있습니다. 저도 그런 경험이 있습니다. 이 글에서는 테스트 중에 API 요청을 모의하는 더 간단하고 효율적인 방법을 안내하겠습니다.
시작하기 전에 사용할 도구 목록은 다음과 같습니다.
- 반응
- React 테스팅 라이브러리
- 농담
- 크라코 : > 나중에 jest 구성을 확장하려면 이 정보가 필요합니다
- MSW(모의근무요원)
모든 것이 익숙하지 않더라도 걱정하지 마세요. 따라만 하시면 각 단계를 안내해 드리겠습니다.
프로젝트에 대한 Github 링크는 다음과 같습니다
개요
우리는 Json Placeholder API를 사용하여 Todos 목록을 가져와 표시하는 간단한 React 앱을 구축할 것입니다. 이 프로젝트에서는 다음 사항을 확인하기 위해 테스트 시나리오를 작성합니다.
- API 요청이 진행되는 동안 앱에 로딩 상태가 표시됩니다.
- 요청이 실패하면 오류 메시지를 표시합니다.
- API의 데이터 목록이 올바르게 렌더링되는지 확인합니다.
- 요청이 성공했지만 데이터가 반환되지 않는 경우 피드백을 제공합니다.
이 가이드에서는 두 가지 주요 접근 방식을 다룹니다.
- API 호출을 모의하는 전통적인 방법
- MSW(Mock Service Worker)를 활용한 현대적 접근
시작해 보세요!
앱 구축을 시작하려면 다음 단계를 따르세요.
1. 새 React 앱 만들기: 다음 명령을 실행하여 React 애플리케이션을 만듭니다.
npx create-react-app msw-example
2. 애플리케이션 시작: 설정 후 프로젝트 폴더로 이동하여 다음을 실행합니다.
npm start
3. 필요한 패키지 설치: 다음으로 @tanstack/react-query를 설치하여 클라이언트측 데이터를 관리합니다.
npm install @tanstack/react-query
React Query(Tanstack Query)는 캐싱, 동기화, 데이터 가져오기 등 서버 측 상태 관리를 처리하는 데 도움이 됩니다. 공식 문서에서 이에 대해 자세히 알아볼 수 있습니다
이제 앱 로직 작성을 시작하고 React Query를 설정하여 데이터 가져오기를 효율적으로 관리할 수 있습니다. 설정 후의 모습은 이렇습니다.
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { Todos } from "components/Todos"; const queryClient = new QueryClient(); function App() { return ( <queryclientprovider client="{queryClient}"> <div data-testid="app" classname="App"> <todos></todos> </div> </queryclientprovider> ); } export default App;
다음으로 할 일 목록을 렌더링하는 Todos 구성 요소를 만듭니다.
Todos.js
import { useQuery } from "@tanstack/react-query"; import { getTodos } from "api/todo"; export function Todos() { const { data, isError, isLoading } = useQuery({ queryFn: getTodos, queryKey: ["TODOS"], }); if (isLoading) { return <p>loading todo list</p>; } if (isError) { return <p>an error occurred fetching todo list</p>; } return ( <div> {Boolean(data.length) ? ( <ol> {data.map((item) => ( <li key="{item.id}">{item.title}</li> ))} </ol> ) : ( <p>You do not have todos created yet</p> )} </div> ); }
이제 모든 것이 설정되었으므로 앞서 설명한 시나리오에 대한 테스트 작성을 시작하겠습니다. 먼저, 우리에게 이미 익숙한 전통적인 접근 방식, 즉 Jest를 사용하여 API 호출을 모의하는 방법을 사용하여 이를 구현하겠습니다
따라갈 수 있도록 github 저장소를 확인하세요
API 호출을 모의하는 전통적인 방법
React와 Jest는 기본적으로 함께 원활하게 작동하므로 적어도 현재로서는 추가 구성이나 설정이 필요하지 않습니다. Todo.js 구성 요소 옆에 Todos.test.js라는 파일을 생성하고 여기서 Todos 구성 요소를 가져와서 테스트를 작성합니다..
할일 목록을 검색하고 응답을 반환하는 API 호출을 담당하는 getTodos라는 함수가 있습니다.
export async function getTodos() { const response = await fetch("https://jsonplaceholder.typicode.com/todos", { headers: { "Content-Type": "application/json", }, }); if (!response.ok) { const res = await response.json(); throw new Error(res.message || response.status); } return response.json(); }
Todos.test.js 파일에서 Todos 구성 요소를 가져오고 React 쿼리 공급자와 함께 래퍼를 제공하는 유틸리티 함수를 생성해야 합니다. 이렇게 하면 Todos 구성 요소와 해당 하위 요소가 테스트에서 서버 상태를 관리하기 위해 반응 쿼리를 사용할 수 있습니다.
import { render, screen, waitFor, within } from "@testing-library/react"; import { Todos } from "./Todos"; import { reactQueryWrapper } from "utils/reactQueryWrapper"; import { getTodos } from "api/todo"; const { wrapper, queryCache } = reactQueryWrapper();
다음으로 getTodos 함수를 모의해야 합니다. 이를 통해 각 테스트 시나리오에 대한 반환 값을 지정할 수 있으므로 테스트 중에 함수가 반환하는 데이터를 제어할 수 있습니다. 또한 이전 테스트 사례에서 남은 데이터를 모두 정리하여 각 테스트 사례가 깨끗한 상태에서 시작되도록 할 것입니다.
코드 샘플
jest.mock("api/todo", () => ({ getTodos: jest.fn(), })); afterEach(() => { queryCache.clear(); jest.clearAllMocks(); });
Todos.test.js
import { render, screen, waitFor, within } from "@testing-library/react"; import { Todos } from "./Todos"; import { reactQueryWrapper } from "utils/reactQueryWrapper"; import { getTodos } from "api/todo"; const { wrapper, queryCache } = reactQueryWrapper(); jest.mock("api/todo", () => ({ getTodos: jest.fn(), })); afterEach(() => { queryCache.clear(); }); afterEach(() => { jest.clearAllMocks(); });
첫 번째 테스트 시나리오: 렌더링 로드 상태
요청이 진행되는 동안 구성 요소가 로드 상태를 올바르게 표시하는지 확인하고 싶습니다.
test("Renders loading state", () => { getTodos.mockImplementation(() => { return new Promise((resolve) => { setTimeout(() => { resolve(); }, 1000); }); }); render(<todos></todos>, { wrapper }); const loadingText = screen.getByText("loading todo list"); expect(loadingText).toBeInTheDocument(); });
두 번째 테스트 시나리오: 요청이 실패하거나 네트워크 오류가 있는 경우 오류 상태를 렌더링
우리는 API 요청이 실패하거나 네트워크 오류가 발생할 때 구성 요소가 오류 상태를 올바르게 렌더링하는지 확인하고 싶습니다.
test("Renders error state when request fails or there is network error", async () => { getTodos.mockImplementationOnce(() => { return new Promise((resolve, reject) => { reject(); }); }); render(<todos></todos>, { wrapper }); await screen.findByText("an error occurred fetching todo list"); expect( screen.getByText("an error occurred fetching todo list") ).toBeInTheDocument(); });
세 번째 테스트 시나리오: 할 일 목록 렌더링
요청이 성공하면 구성 요소가 할 일 목록을 올바르게 렌더링하는지 확인하고 싶습니다.
test("Renders list of todos", async () => { getTodos.mockImplementation(() => { return Promise.resolve([ { id: 1, title: "Exercise" }, { id: 2, title: "Cook" }, ]); }); render(<todos></todos>, { wrapper }); const loadingText = screen.queryByText("loading todo list"); await waitFor(() => expect(loadingText).not.toBeInTheDocument()); const list = screen.getByRole("list"); expect(list).toBeInTheDocument(); expect(within(list).getAllByRole("listitem")).toHaveLength(2); });
네 번째 테스트 시나리오: 할 일 목록 렌더링
API 요청이 빈 할 일 목록을 반환할 때 구성 요소가 피드백 메시지를 올바르게 렌더링하는지 확인하고 싶습니다.
test("Renders feedback message when user has an empty list of todos", async () => { getTodos.mockImplementationOnce(() => { return Promise.resolve([]); }); render(<todos></todos>, { wrapper }); await waitFor(() => expect(screen.queryByText("loading todo list")).not.toBeInTheDocument() ); expect( screen.getByText("You do not have todos created yet") ).toBeInTheDocument(); });
Great! Now that we've covered mocking API calls with Jest, let’s explore a better approach using Mock Service Worker (MSW). MSW provides a more elegant and maintainable way to mock API calls by intercepting network requests at the network level rather than within your tests.
Introducing MSW (Mock Service Worker)
Mock Service Worker (MSW) is an API mocking library designed for both browser and Node.js environments. It allows you to intercept outgoing requests, observe them, and provide mocked responses. MSW helps you simulate real-world scenarios in your tests, making them more robust and reliable.
Read more about MSW
Setting Up MSW
Step 1: Install MSW using the following command:
npm install msw@latest --save-dev
Step 2: Set up the environment you wish to intercept requests in—either Browser or Node. Before doing so, create a mock directory within your src directory. Inside this directory, you'll create the following files and directories:
browser.js: Handles request interception in the browser environment.
server.js: Handles request interception in the Node.js environment.
handlers: A directory containing files that define the API endpoints to intercept.
Here’s how your folder structure should look:
src/ └── mock/ ├── browser.js ├── server.js └── handlers/
This setup ensures that you have a clear organization for intercepting and handling requests in both browser and Node.js environments using MSW.
Browser Environment Setup
To set up MSW for intercepting requests in the browser, follow these steps:
1. Create the browser.js File
In your src/mock directory, create a file named browser.js. This
file will set up the MSW worker to intercept requests in the
browser environment.
// src/mock/browser.js import { setupWorker } from 'msw/browser'; // Create a worker instance to intercept requests export const worker = setupWorker();
2. Generate the mockServiceWorker.js File
This file is required for MSW to function properly in the browser.
Generate it using the following command from the root directory of
your application:
npx msw init <public_dir> --save </public_dir>
This command initializes the MSW service worker and places the mockServiceWorker.js file into the public directory of your React app.
3. Start the Service Worker
Import and start the worker in your application entry point
(typically index.js or App.js).
// src/index.js import React from "react"; import ReactDOM from "react-dom/client"; import "./index.css"; import App from "./App"; import reportWebVitals from "./reportWebVitals"; if (process.env.NODE_ENV === "development") { const mswState = localStorage.getItem("mswState") === "enabled"; if (mswState) { const { worker } = require("./mocks/browser"); worker.start(); window.__mswStop = worker.stop; } } const root = ReactDOM.createRoot(document.getElementById("root")); root.render( <react.strictmode> <app></app> </react.strictmode> );
4. Verify the Setup
To ensure that the service worker is correctly set up, navigate to
the URL of your application in the browser:
http://localhost:3000/mockServiceWorker.js
You should see the service worker script displayed in your browser. This confirms that the service worker is correctly installed and ready to intercept requests.
If your MSW setup is correct and enabled, you should see a console message indicating that MSW is active. Your browser console should display logs similar to this:
These logs confirm that the MSW service worker is properly intercepting network requests and is ready to mock API responses according to the handlers you’ve defined.
Node Environment Setup
To set up MSW for intercepting requests in a Node.js environment (for example, in server-side tests), follow these steps:
Step 1: Create the server.js File
In the src/mock directory, create a file named server.js. This file sets up the MSW server to intercept requests in a Node.js environment.
// src/mock/server.js import { setupServer } from "msw/browser"; // Create a server instance with the defined request handlers export const server = setupServer();
Step 2: Define the API Handlers
Create a file named posts.js in the handlers directory.This file will describe the APIs you want to intercept and the mock responses.
// src/mock/handlers/posts.js import { http, HttpResponse } from "msw"; export const postHandlers = [ // Handler for GET /todos request http.get("https://jsonplaceholder.typicode.com/todos", () => { return HttpResponse.json([ { id: 1, title: "totam quia non" }, { id: 2, title: "sunt cum tempora" }, ]); }), ];
Here, we're defining that when MSW intercepts a GET request to https://jsonplaceholder.typicode.com/todos, it should respond with a 200 status code and the provided JSON data.
Step 3: Hook Handlers to the Browser Worker
Update the browser.js file to include the defined handlers.
import { setupWorker } from "msw/browser"; import { postHandlers } from "./handlers/posts"; export const worker = setupWorker(...postHandlers);
Step 4: Hook Handlers to the Node Server
Ensure the handlers are also used in the Node.js environment by updating the server.js file.
import { setupServer } from "msw/node"; import { postHandlers } from "./handlers/posts"; export const server = setupServer(...postHandlers);
With these configurations in place, your MSW setup is complete and ready for both browser and Node.js environments. Congratulations on completing the setup! ?
Using MSW in our Tests
To use MSW in your tests, you need to set up your test environment to utilize the mock server for intercepting API calls. Here’s a guide to setting up and writing tests using MSW with your Todos component.
Create the Test File
Create a new file named Todos.MSW.test.js next to your
Todos.jscomponent. This file will contain your tests that
utilize MSW for mocking API responses.Set Up Test Environment
In your Todos.MSW.test.js file, import the necessary modules and
set up the environment for using MSW with your tests. Below is an
example setup:
import { render, screen, waitFor, within } from "@testing-library/react"; import { http, delay, HttpResponse } from "msw"; import { Todos } from "./Todos"; import { reactQueryWrapper } from "utils/reactQueryWrapper"; import { server } from "mocks/server"; const { wrapper, queryCache } = reactQueryWrapper(); afterEach(() => { queryCache.clear(); }); afterEach(() => { jest.clearAllMocks(); }); beforeAll(() => server.listen()); afterEach(() => server.resetHandlers()); afterAll(() => server.close());
First Test Scenario: Renders loading state
We want to verify that our component correctly displays the loading state while the request is in progress.
test("Renders loading state", () => { server.use( http.get("https://jsonplaceholder.typicode.com/todos", async () => { await delay(1000); return HttpResponse.json([]); }) ); render(<todos></todos>, { wrapper }); const loadingText = screen.getByText("loading todo list"); expect(loadingText).toBeInTheDocument(); });
Second Test Scenario: Renders error state when request fails or there is network error
We want to verify that the component correctly renders an error state when the API request fails or encounters a network error.
test("Renders error state when request fails or there is network error", async () => { server.use( http.get("https://jsonplaceholder.typicode.com/todos", async () => { return HttpResponse.json([], { status: 500, }); }) ); render(<todos></todos>, { wrapper }); await screen.findByText("an error occurred fetching todo list"); expect( screen.getByText("an error occurred fetching todo list") ).toBeInTheDocument(); });
Third Test Scenario: Renders list of todos
We want to verify that our component correctly renders the list of todos when the request is successful.
test("Renders list of todos", async () => { render(<todos></todos>, { wrapper }); const loadingText = screen.queryByText("loading todo list"); await waitFor(() => expect(loadingText).not.toBeInTheDocument()); const list = screen.getByRole("list"); expect(list).toBeInTheDocument(); expect(within(list).getAllByRole("listitem")).toHaveLength(2); });
Fourth Test Scenario: Renders list of todos
We want to verify that your component correctly renders a feedback message when the API request returns an empty list of todos.
test("Renders feedback message when user has an empty list of todos", async () => { server.use( http.get("https://jsonplaceholder.typicode.com/todos", () => { return HttpResponse.json([]); }) ); render(<todos></todos>, { wrapper }); await waitFor(() => expect(screen.queryByText("loading todo list")).not.toBeInTheDocument() ); expect( screen.getByText("You do not have todos created yet") ).toBeInTheDocument(); });
Final Thoughts
Mocking API calls is crucial for effective testing, allowing you to simulate different scenarios without relying on real backend services. While traditional Jest mocking can be effective, MSW offers a more sophisticated solution with better support for various environments and more realistic request handling.
Here are a few tips to keep in mind:
Choose the Right Tool: Use MSW for a more comprehensive
solution that integrates seamlessly with your React application,
especially when dealing with complex request handling.Organize Your Handlers: Keep your API handlers well-organized
and modular to make them easier to maintain and extend.Clean Up After Tests: Ensure that your tests clean up properly
by resetting handlers and clearing mocks to avoid interference
between tests.Verify Setup: Always check your setup by inspecting the network
requests and responses to ensure that everything is working as
expected.
By incorporating MSW into your testing strategy, you'll achieve more reliable and maintainable tests, leading to a smoother development experience and higher quality software.
Happy testing! ?
위 내용은 모의 네트워크 요청이 쉬워졌습니다: Jest와 MSW 통합의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

JavaScript 프레임 워크의 힘은 개발 단순화, 사용자 경험 및 응용 프로그램 성능을 향상시키는 데 있습니다. 프레임 워크를 선택할 때 : 1. 프로젝트 규모와 복잡성, 2. 팀 경험, 3. 생태계 및 커뮤니티 지원.

서론 나는 당신이 이상하다는 것을 알고 있습니다. JavaScript, C 및 Browser는 정확히 무엇을해야합니까? 그들은 관련이없는 것처럼 보이지만 실제로는 현대 웹 개발에서 매우 중요한 역할을합니다. 오늘 우리는이 세 가지 사이의 밀접한 관계에 대해 논의 할 것입니다. 이 기사를 통해 브라우저에서 JavaScript가 어떻게 실행되는지, 브라우저 엔진의 C 역할 및 웹 페이지의 렌더링 및 상호 작용을 유도하기 위해 함께 작동하는 방법을 알게됩니다. 우리는 모두 JavaScript와 브라우저의 관계를 알고 있습니다. JavaScript는 프론트 엔드 개발의 핵심 언어입니다. 브라우저에서 직접 실행되므로 웹 페이지를 생생하고 흥미롭게 만듭니다. 왜 Javascr

Node.js는 크림 덕분에 효율적인 I/O에서 탁월합니다. 스트림은 메모리 오버로드를 피하고 큰 파일, 네트워크 작업 및 실시간 애플리케이션을위한 메모리 과부하를 피하기 위해 데이터를 점차적으로 처리합니다. 스트림을 TypeScript의 유형 안전과 결합하면 Powe가 생성됩니다

파이썬과 자바 스크립트 간의 성능과 효율성의 차이는 주로 다음과 같이 반영됩니다. 1) 해석 된 언어로서, 파이썬은 느리게 실행되지만 개발 효율이 높고 빠른 프로토 타입 개발에 적합합니다. 2) JavaScript는 브라우저의 단일 스레드로 제한되지만 멀티 스레딩 및 비동기 I/O는 Node.js의 성능을 향상시키는 데 사용될 수 있으며 실제 프로젝트에서는 이점이 있습니다.

JavaScript는 1995 년에 시작하여 Brandon Ike에 의해 만들어졌으며 언어를 C로 실현했습니다. 1.C Language는 JavaScript의 고성능 및 시스템 수준 프로그래밍 기능을 제공합니다. 2. JavaScript의 메모리 관리 및 성능 최적화는 C 언어에 의존합니다. 3. C 언어의 크로스 플랫폼 기능은 자바 스크립트가 다른 운영 체제에서 효율적으로 실행하는 데 도움이됩니다.

JavaScript는 브라우저 및 Node.js 환경에서 실행되며 JavaScript 엔진을 사용하여 코드를 구문 분석하고 실행합니다. 1) 구문 분석 단계에서 초록 구문 트리 (AST)를 생성합니다. 2) 컴파일 단계에서 AST를 바이트 코드 또는 기계 코드로 변환합니다. 3) 실행 단계에서 컴파일 된 코드를 실행하십시오.

Python 및 JavaScript의 미래 추세에는 다음이 포함됩니다. 1. Python은 과학 컴퓨팅 분야에서의 위치를 통합하고 AI, 2. JavaScript는 웹 기술의 개발을 촉진하고, 3. 교차 플랫폼 개발이 핫한 주제가되고 4. 성능 최적화가 중점을 둘 것입니다. 둘 다 해당 분야에서 응용 프로그램 시나리오를 계속 확장하고 성능이 더 많은 혁신을 일으킬 것입니다.

개발 환경에서 Python과 JavaScript의 선택이 모두 중요합니다. 1) Python의 개발 환경에는 Pycharm, Jupyternotebook 및 Anaconda가 포함되어 있으며 데이터 과학 및 빠른 프로토 타이핑에 적합합니다. 2) JavaScript의 개발 환경에는 Node.js, VScode 및 Webpack이 포함되어 있으며 프론트 엔드 및 백엔드 개발에 적합합니다. 프로젝트 요구에 따라 올바른 도구를 선택하면 개발 효율성과 프로젝트 성공률이 향상 될 수 있습니다.


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

SecList
SecLists는 최고의 보안 테스터의 동반자입니다. 보안 평가 시 자주 사용되는 다양한 유형의 목록을 한 곳에 모아 놓은 것입니다. SecLists는 보안 테스터에게 필요할 수 있는 모든 목록을 편리하게 제공하여 보안 테스트를 더욱 효율적이고 생산적으로 만드는 데 도움이 됩니다. 목록 유형에는 사용자 이름, 비밀번호, URL, 퍼징 페이로드, 민감한 데이터 패턴, 웹 셸 등이 포함됩니다. 테스터는 이 저장소를 새로운 테스트 시스템으로 간단히 가져올 수 있으며 필요한 모든 유형의 목록에 액세스할 수 있습니다.

Atom Editor Mac 버전 다운로드
가장 인기 있는 오픈 소스 편집기

에디트플러스 중국어 크랙 버전
작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음

PhpStorm 맥 버전
최신(2018.2.1) 전문 PHP 통합 개발 도구

DVWA
DVWA(Damn Vulnerable Web App)는 매우 취약한 PHP/MySQL 웹 애플리케이션입니다. 주요 목표는 보안 전문가가 법적 환경에서 자신의 기술과 도구를 테스트하고, 웹 개발자가 웹 응용 프로그램 보안 프로세스를 더 잘 이해할 수 있도록 돕고, 교사/학생이 교실 환경 웹 응용 프로그램에서 가르치고 배울 수 있도록 돕는 것입니다. 보안. DVWA의 목표는 다양한 난이도의 간단하고 간단한 인터페이스를 통해 가장 일반적인 웹 취약점 중 일부를 연습하는 것입니다. 이 소프트웨어는
