React Hooks용 단위 테스트 작성

React 후크는 React 구성 요소 간에 논리를 공유하기 위한 우아한 패턴입니다. 개념에 익숙하지 않은 경우 자세한 내용을 읽을 수 있습니다here.

내가 최근에 사용자 정의 React 후크를 만들 때 직면한 문제 중 하나는 후크를 사용하는 모든 다른 구성 요소와 독립적으로 기능을 테스트하기 위한 명확한 전략을 파악하는 것이었습니다.

예를 들어, 10개의 서로 다른 구성 요소에서 다음 후크를 사용하고 있다고 가정합니다.

import { useState, useEffect } from 'react';

function useExample() {
  const [value, setValue] = useState(0);

  useEffect(() => setValue(1), []);

  return value;
}

이 후크는 처음에 0과 같은 값을 반환하고 초기 렌더링 후에는 1과 같은 값을 반환합니다. 여러 구성 요소에서 이 논리를 단위 테스트하는 대신 이 후크에 특정한 테스트를 작성하는 것이 좋습니다.

이 후크에 대한 단위 테스트를 작성하려면 극복해야 할 두 가지 과제가 있습니다.
  • 단순히 expect(useExample()).toBe... 효과에 대해 무언가를 실행할 수 없습니다. 렌더링 중인 구성 요소 외부에서 후크를 호출했다는 React 오류를 반환하기 때문입니다.
  • 초기 후크 값과 렌더링 후 값을 테스트하기 위해 명확한 패턴이 필요합니다.

  • 이러한 문제를 해결하기 위해 간단한 테스트 유틸리티 함수를 만들 수 있었습니다.

    import React from 'react';
    import { shallow, mount } from 'enzyme';
    
    export default function testHook(runHook, flushEffects = true) {
      function HookWrapper() {
        const output = runHook();
    
        return (
          <span output={output} />
        );
      }
    
      const wrapperFunc = flushEffects ? mount : shallow;
      const wrapper = wrapperFunc(<HookWrapper />);
    
      return wrapper.find('span').props().output;
    }
    

    이제 사용자 지정 React 후크를 이 함수에 전달하여 쉽게 단위 테스트할 수 있습니다. 다음은 이전에 Jest를 사용하여 만든 사용자 지정 후크 예제를 테스트하는 방법의 예입니다.

    import useExample from '../src/js/hooks/useExample';
    import testHook from './_test-hook';
    
    test('Initial value is 0', () => {
      const value = testHook(() => useExample(), false);
      expect(value).toBe(0);
    });
    
    test('Value after render is 1', () => {
      const value = testHook(() => useExample());
      expect(value).toBe(1);
    });
    

    애플리케이션이 컨텍스트 값에 의존하는 후크를 사용하는 경우 동일한 컨텍스트 공급자로 HookWrapper를 래핑하고 활용하려는 컨텍스트 값을 전달할 수도 있습니다.

    import React from 'react';
    import { shallow, mount } from 'enzyme';
    import { ApplicationContext, defaultApplicationState } from '../src/js/Application';
    
    export default function testHook(runHook, flushEffects = true, useApplicationContext = null) {
      function HookWrapper() {
        const output = runHook();
    
        return (
          <span output={output} />
        );
      }
    
      let Container = null;
    
      if (useApplicationContext) {
        const value = {
          ...defaultApplicationState,
          state: useApplicationContext(defaultApplicationState),
        };
    
        Container = ({ children }) => (
          <ApplicationContext.Provider value={value}>
            {children}
          </ApplicationContext.Provider>
        );
      }
    
      const wrapperFunc = flushEffects ? mount : shallow;
    
      const wrapper = wrapperFunc(Container ? (
        <Container>
          <HookWrapper />
        </Container>
      ) : (
        <HookWrapper />
      ));
    
      return wrapper.find('span').props().output;
    }
    

    설명하기 위해 다음은 컨텍스트 값에 의존하는 간단한 후크입니다. 기본적으로 반환 값을 0으로 설정합니다. 컨텍스트 값이 유효한 숫자이면 이를 상태 값으로 설정합니다.

    import { useState, useEffect, useContext } from 'react';
    import { ApplicationContext } from '../Application'; 
    
    function useExampleContext() {
      const [value, setValue] = useState(0);
      const { contextValue } = useContext(ApplicationContext);
    
      useEffect(() => {
        if (contextValue !== value && typeof contextValue === 'number') {
          setValue(contextValue);
        }
      }, [contextValue]);
    
      return value;
    }
    

    이제 다음과 같은 방식으로 후크를 테스트할 수 있습니다.

    test('Initial value is 0', () => {
      const value = testHook(() => useExampleContext(), false);
      expect(value).toBe(0);
    });
    
    test('Value matches context value', () => {
      const value = testHook(() => useExampleContext(), true, (state) => ({ ...state, contextValue: 1 }));
      expect(value).toBe(1);
    });
    



    이 게시물이 사용자 정의 React 후크를 단위 테스트하려는 다른 사람에게 도움이 되었기를 바라며 다른 사람들이 이 문제를 어떻게 처리했는지 궁금합니다!

    좋은 웹페이지 즐겨찾기