Unit Test | 3.3. 리액트 훅 테스트(feat. act 함수)

Kate Jung·2024년 2월 10일
0

Front-end Test

목록 보기
10/17
post-thumbnail
post-custom-banner

📌 리액트 훅

  • 독립적인 단위 테스트를 작성하기 좋은 케이스

    React Testing Library을 사용하면 별도의 Hook으로 추상한 로직들의 상태가 올바르게 변경되는지 손쉽게 검증 가능

📌 예시 | useConfirmModal

🔹 hook에 대한 설명

  • 기능

    모달의 Open 상태에 대한 로직 처리

  • 단위 테스트로 검증하는 이유

    • 안정성을 위해

      (모달의 동작을 제어할 필요가 있는 모든 컴포넌트에서 사용되기 때문)

  • 단위 테스트로 작성하기 좋은 이유

    • 독립적인 함수이기 때문

      (외부 모듈에 대한 의존성 없이 독립적으로 동작하는 함수이기 때문)

🔹 useConfirmModal.jsx

import { useState } from 'react';

const useConfirmModal = (initialValue = false) => {
  const [isModalOpened, setIsModalOpened] = useState(initialValue);

  const toggleIsModalOpened = () => {
    setIsModalOpened(!isModalOpened);
  };

  return {
    toggleIsModalOpened,
    isModalOpened,
  };
};

export default useConfirmModal;

🔹 useConfirmModal.spec.jsx

테스트 내용 : 위 hook의 3가지 기능을 검증함 (테스트 description 참고)

🔸 전체 코드

import { renderHook, act } from '@testing-library/react';

import useConfirmModal from './useConfirmModal';

// 1️⃣ 번째 테스트
it('호출 시 initialValue 인자를 지정하지 않는 경우 isModalOpened 상태가 false로 설정된다.', () => {
  const { result, rerender } = renderHook(useConfirmModal);

  expect(result.current.isModalOpened).toBe(false);
});

// 2️⃣ 번째 테스트
it('호출 시 initialValue 인자를 boolean 값으로 지정하는 경우 해당 값으로 isModalOpened 상태가 설정된다.', () => {
  const { result } = renderHook(() => useConfirmModal(true)); // 👈 다른 부분

  expect(result.current.isModalOpened).toBe(true);
});

// 3️⃣ 번째 테스트
it('훅의 toggleIsModalOpened()를 호출하면 isModalOpened 상태가 toggle된다.', () => {
  const { result } = renderHook(useConfirmModal);

  act(() => {
    result.current.toggleIsModalOpened();
  });

  expect(result.current.isModalOpened).toBe(true);
});
  • React Hook 기능 검증 방법
    Hook을 호출 후, Hook에서 반환하는 state (ex. IsModalOpened)가 올바르게 변경되는지 확인

  • 리액트 훅은 반드시 리액트 컴포넌트 내에서만 호출되어야 정상적으로 실행

    React Testing Library에서는 RenderHook API를 제공

    (React 컴포넌트 없이도 React Hook의 기본 기능을 쉽게 검증할 수 있도록)

🔸 1번째 테스트

  • RenderHook API를 통해 useConfirmModalHook을 실행하면 result와 rerender란 값을 반환 받음

    • result

      • 훅을 호출하여 얻은 결과 값을 반환

      • result.current 값의 참조를 통해 Hook 내부의 최신 상태 추적 가능

    • rerender

      • 훅을 원하는 인자와 함께 새로 호출하여 상태를 갱신한다.

        특정 Hook을 원하는 인자로 호출 시, 새로운 상태로 변경되는지 확인하고 싶을 때 re-render API를 사용하면 원하는 대로 Hook이 변경되는지 확인 가능

  • toBe

    • 원시값의 동등을 판별

    • 이 매처를 사용하여 훅이 반환한 초기 isModalOpened State가 false인지 단언

🔸 2번째 테스트

  • 이전의 테스트와 대부분 동일

    (다른 점 : Initial Value를 초기 값으로 지정)

🔸 3번째 테스트

  • 확인 할 것

    toggleIsModalOpened란 함수 호출에 따라 isModalOpened state가 변경되는지

  • toggleIsModalOpened 함수 호출 방법

    resultcurrent 참조

  • act 없이 toggleIsModalOpened 함수 호출 시 에러 발생

    • 직접 상태를 변경하는 코드가 있을 경우 (React Testing Library의 render 함수나 user-event의 모듈을 사용하지 않고)

      act 함수로 감싸 주어야 함

📌 act 함수

🔹 공식문서

링크

🔹 역할

🔹 지금껏 act 함수 없이 테스트가 통과한 이유

(React Testing Library의 render 함수와 user-event는 컴포넌트 렌더링, 이벤트 핸들러 처리를 할 때)

내부적으로 act 함수를 호출하여 동작하기 때문

📌 정리


참고

  • 실무에 바로 적용하는 프런트엔드 테스트
profile
복습 목적 블로그 입니다.
post-custom-banner

0개의 댓글