jest @react testing library 로 Redux 사용하는 컴포넌트 테스트하기 - boostcamp-2020/Project15-C-Client-Based-Formula-Editor GitHub Wiki

jest + @react-testing-library로 테스트를 하고 있었다.

제일 작은 단위인 @ingredients를 테스트 하고 있는데 일반적인 컴포넌트는 테스트가 되는데 Redux를 사용하는 테스트는 통과하지 못 하며 에러가 났다. 문제는 해당 컴포넌트 안에서 Redux를 사용하고 있기 때문이었다.

Redux를 사용하기 위해서는 Provider 안에서만 사용해야한다. 그런데 test 환경은 원래 개발환경이 아니라 다른 환경에서 실행되는 것이기 때문에 Provider를 감싸놓은 index.tsx 안에서 실행되지 않는다. 그래서 Provider를 생성해서 컴포넌트를 감싸주어야했다. 그런데 Redux를 사용하는 컴포넌트 마다 Provider를 생성해서 하는 것은 너무 비효율적인 것 같았고, 반복되는 코드가 너무 반복되는 느낌이었다.

그래서 Redux 공식 홈페이지에서 소개돼있는 방법으로 test-util.tsx를 만들어보았다.

lib/utils/test-util.tsx

import React from 'react';
import { render as rtlRender } from '@testing-library/react';
import { createStore, Store } from 'redux';
import { Provider } from 'react-redux';
import reducer, { RootState } from '../../contexts';

function render(
  ui: React.ReactElement,
  {
    initialState: {number: 0}, // 초기값을 넣어준다.
    store = createStore(reducer, initialState),
  }: { initialState?: RootState; store?: Store } = { initialState: undefined, store: undefined } // 타입과 초기값을 넣어준다.
) {
  function Wrapper({ children }: { children?: React.ReactNode }) { // Wrapper를 만들어준다.
    return <Provider store={store}>{children}</Provider>;
  }
  return rtlRender(ui, { wrapper: Wrapper }); // 원래 @testing-library/react 의 안에 있는 render 함수의
}                                             // 두번째인자에 여러가지를 받을 수 있는데 그중에 wrapper 가 있다. wrapper에 함수 or 클래스 컴포넌트를 넣어주면
																							// 첫번째인자를 children으로 감싸준다.

// @testing-library/react를 안 불러오고 test-util.tsx에서 다 불러올 수 있게 다시 내보내준다.
export * from '@testing-library/react';
// render 함수를 override 해준다.
export { render };

그러면 다음과 같이 사용하면 된다.

test/PageItem.test.tsx

import * as React from 'react';
import { render } from '../lib/utils/test-util'; // test-util에서 render 등 모든 함수를 불러올 수 있음.
import PageTabItem from '../components/Ingredients/PageTabItem';
import '@testing-library/jest-dom';

describe('PageItem TEST', () => {
  const testInfo = {
    id: 0,
    latex: '\\frac',
    fontSize: '16',
    fontColor: 'black',
    textAlign: 'center',
  };

  test('PageItem title 테스트 ', () => {
    const { container } = render(<PageTabItem isCurrentTab={false} index={3} item={testInfo} />); // 2번째 인자를 넣어주지 않으면 설정해놓은 기본값이 Provider의 초기값으로 들어간다.

    expect(container).toHaveTextContent('수식 4');
  });
});

현재 PageItem 컴포넌트 안에서 redux를 사용하고 있지만 테스트를 해보면 잘 되는 것을 확인할 수 있다.

image

⚠️ **GitHub.com Fallback** ⚠️