Waylog Blog

Jest와 React Testing Library로 단위 테스트 정복하기

Testing

테스트 코드를 짜야한다고 하면 "시간이 없어서요"라는 변명이 가장 먼저 나옵니다. 하지만 테스트가 없는 코드는 시한폭탄과 같습니다. 리팩터링을 할 때마다 "이거 고치면 저게 터지지 않을까?" 하는 두려움에 떨게 되죠. 프론트엔드 테스트의 표준인 Jest와 **React Testing Library (RTL)**를 통해 견고한 애플리케이션을 만드는 법을 알아봅시다.

1. Testing Library의 철학

과거 Enzyme 같은 라이브러리는 컴포넌트의 내부 상태(state)나 메서드에 직접 접근하여 테스트했습니다. 이는 구현 상세(Implementation Detail)에 의존하는 깨지기 쉬운 테스트를 만듭니다. 반면 RTL은 **"사용자가 소프트웨어를 사용하는 방식대로 테스트하라"**는 철학을 가집니다. 사용자는 컴포넌트의 state가 무엇인지 모릅니다. 그저 화면에 "저장" 버튼이 보이고, 그걸 누르면 "저장되었습니다"라는 문구가 뜨는 것을 알 뿐이죠.

2. 쿼리의 우선순위

RTL은 요소를 찾는 다양한 메서드(Query)를 제공합니다. 권장되는 우선순위가 있습니다.

  1. getByRole: button, heading, textbox 등 접근성 역할을 기반으로 찾습니다. 가장 권장됩니다.
  2. getByLabelText: 폼(Form) 요소에 연결된 라벨로 찾습니다.
  3. getByPlaceholderText: 입력창의 플레이스홀더로 찾습니다.
  4. getByText: 화면에 보이는 텍스트 내용으로 찾습니다.
  5. getByTestId: data-testid 속성을 사용하는 최후의 수단입니다.

3. Mocking의 미학 (MSW)

백엔드 API가 완성되지 않았거나, 네트워크 비용을 아끼기 위해 API 호출을 모킹(가짜로 대체)해야 합니다. jest.mock을 쓸 수도 있지만, 최근에는 **MSW (Mock Service Worker)**가 대세입니다. 서비스 워커 레벨에서 네트워크 요청을 가로채서 미리 정의된 핸들러로 응답하므로, 실제 API를 호출하는 것과 똑같은 환경에서 테스트할 수 있습니다.

4. 좋은 테스트의 조건

  • 빠르다: 느린 테스트는 안 돌리게 됩니다.
  • 독립적이다: A 테스트의 결과가 B 테스트에 영향을 주면 안 됩니다.
  • 리팩터링 내성: 내부 구현을 바꿔도(변수명 변경 등) 기능이 같다면 테스트는 통과해야 합니다.

테스트 코드는 개발자의 수면 시간을 지켜주는 가장 저렴한 보험입니다.