Contents
see List작성일 2025. 11. 30.
Jest와 React Testing Library
Jest는 Facebook에서 만든 JavaScript 테스트 프레임워크이고, React Testing Library는 사용자 관점에서 React 컴포넌트를 테스트하는 라이브러리입니다. 함께 사용하면 효과적인 프론트엔드 테스트를 작성할 수 있습니다.
언제 사용하나요?
- React 컴포넌트 렌더링 및 동작 테스트
- 사용자 인터랙션 시뮬레이션
- API 호출 모킹
- CI/CD 파이프라인에서 자동화된 테스트
설치
# Create React App에는 이미 포함됨
npm install --save-dev jest @testing-library/react @testing-library/jest-dom @testing-library/user-event기본 테스트 구조
// Button.test.js
import { render, screen, fireEvent } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import Button from "./Button";
describe("Button 컴포넌트", () => {
it("버튼 텍스트가 렌더링된다", () => {
render(<Button>클릭</Button>);
expect(screen.getByText("클릭")).toBeInTheDocument();
});
it("클릭 시 onClick이 호출된다", async () => {
const handleClick = jest.fn();
render(<Button onClick={handleClick}>클릭</Button>);
await userEvent.click(screen.getByRole("button"));
expect(handleClick).toHaveBeenCalledTimes(1);
});
});쿼리 메서드
// getBy - 요소가 없으면 에러
screen.getByText("Hello");
screen.getByRole("button");
screen.getByLabelText("이메일");
screen.getByPlaceholderText("입력하세요");
screen.getByTestId("submit-btn");
// queryBy - 요소가 없으면 null (없음 확인용)
expect(screen.queryByText("에러")).not.toBeInTheDocument();
// findBy - 비동기, Promise 반환
const item = await screen.findByText("로딩 완료");
// 복수형 - 여러 요소
const buttons = screen.getAllByRole("button");사용자 이벤트 테스트
import userEvent from "@testing-library/user-event";
it("폼 입력 및 제출 테스트", async () => {
const user = userEvent.setup();
const onSubmit = jest.fn();
render(<LoginForm onSubmit={onSubmit} />);
// 입력
await user.type(screen.getByLabelText("이메일"), "[email protected]");
await user.type(screen.getByLabelText("비밀번호"), "password123");
// 체크박스
await user.click(screen.getByLabelText("자동 로그인"));
// 선택 박스
await user.selectOptions(
screen.getByRole("combobox"),
["option1"]
);
// 제출
await user.click(screen.getByRole("button", { name: "로그인" }));
expect(onSubmit).toHaveBeenCalledWith({
email: "[email protected]",
password: "password123",
});
});비동기 테스트
import { render, screen, waitFor } from "@testing-library/react";
it("데이터 로딩 후 목록이 표시된다", async () => {
render(<UserList />);
// 로딩 상태 확인
expect(screen.getByText("로딩 중...")).toBeInTheDocument();
// 데이터 로드 대기
await waitFor(() => {
expect(screen.getByText("사용자1")).toBeInTheDocument();
});
// 또는 findBy 사용
const user = await screen.findByText("사용자1");
expect(user).toBeInTheDocument();
});API 모킹
// api.js 모킹
jest.mock("./api");
import { fetchUsers } from "./api";
beforeEach(() => {
fetchUsers.mockResolvedValue([
{ id: 1, name: "홍길동" },
{ id: 2, name: "김철수" },
]);
});
it("API에서 사용자 목록을 가져온다", async () => {
render(<UserList />);
await screen.findByText("홍길동");
expect(fetchUsers).toHaveBeenCalledTimes(1);
});
// fetch 직접 모킹
global.fetch = jest.fn(() =>
Promise.resolve({
json: () => Promise.resolve({ data: "test" }),
})
);커스텀 훅 테스트
import { renderHook, act } from "@testing-library/react";
import useCounter from "./useCounter";
it("useCounter 훅 테스트", () => {
const { result } = renderHook(() => useCounter(0));
expect(result.current.count).toBe(0);
act(() => {
result.current.increment();
});
expect(result.current.count).toBe(1);
});스냅샷 테스트
it("컴포넌트 스냅샷 일치", () => {
const { container } = render(<Button>테스트</Button>);
expect(container).toMatchSnapshot();
});주요 매처
// jest-dom 매처
expect(element).toBeInTheDocument();
expect(element).toBeVisible();
expect(element).toBeDisabled();
expect(element).toHaveClass("active");
expect(element).toHaveValue("test");
expect(element).toHaveAttribute("type", "submit");
expect(element).toHaveTextContent("Hello");팁
- 구현 상세보다 사용자 행동 테스트
- getByRole을 우선 사용 (접근성 향상)
- act() 경고 시 waitFor 사용
- 테스트 간 격리 (beforeEach로 초기화)
javascript
| No | 작성일 | Title |
|---|---|---|
| 2921 | 2026. 05. 31. | 브라우저 중복 탭 작업 제어: BroadcastChannel과 Web Locks로 자동 저장 충돌 막기 |
| 2866 | 2026. 05. 23. | Node.js 운영 추적 로그 설계: AsyncLocalStorage로 요청 ID와 장애 원인 연결하기 |
| 2787 | 2026. 05. 15. | Node.js fetch 타임아웃·재시도 표준 패턴: AbortSignal로 장애 전파 막기 |
| 2589 | 2026. 04. 23. | ES2026 JavaScript 신기능 완전 가이드: using/await using, Array.fromAsync, Error.isError, Math.sumPrecise 실전 적용 |
| 2490 | 2026. 04. 14. | ES2025/ES2026 완벽 정리: Iterator Helpers, Temporal API, using 키워드 실전 가이드 |
| 2469 | 2026. 04. 13. | ES2026 완벽 가이드: Temporal API, using/await using, Array/Set 신기능 총정리 |
| 2449 | 2026. 04. 12. | ES2025/ES2026 JavaScript 신기능 완벽 정리: Temporal API부터 using 키워드까지 |
| 2425 | 2026. 04. 11. | Node.js 24 LTS 핵심 신기능 완벽 가이드 - V8 13.6, Permission Model, URLPattern |
| 2389 | 2026. 04. 09. | ES2025 핵심 신규 기능 총정리 - Set 연산, Iterator Helpers, Temporal API까지 |
| 2368 | 2026. 04. 08. | ES2025/ES2026 완벽 정리: Temporal API, Resource Management, 새 문법 총정리 |