본문 바로가기

Jest

[Jest] Provider 렌더 로직 함수로 추출하기

개요

  • Jest + TypeScript 환경에서 RouterProvider 또는 ThemeProvider를 테스트 하려고 한다.
  • 실제 컴포넌트에서는 주로 Entry인 App 컴포넌트에 위 Provider를 호출한다.
  • 만약 테스트 코드를 작성할 때 Provider 없이 테스트 하려는 컴포넌트만 렌더링하게되면 실제 컴포넌트와 테스트 환경이 불일치하여 에러가 발생한다.
  • 이를 해결하기 위해 helper 함수로 RouterProviderThemeProvider를 함께 렌더링하는 로직을 함수로 추출해보자.

코드

// renderWithMemoryRouter.tsx

import { render } from '@testing-library/react';
import { ReactNode } from 'react';
import { MemoryRouter } from 'react-router';

type Option = {
  path?:string;
}

export default function renderWithMemoryRouter(
  node:ReactNode,
  { path = '/' }: Option = {},
) {
  return render((
    <MemoryRouter initialEntries={[path]}>
      {node}
    </MemoryRouter>
  ));
}
  • Jest 환경에서는 BrowserRouter가 아닌 MemoryRouter로 컴포넌트를 감싸주어야 한다.
// renderWithThemeProvider.tsx

import { render } from '@testing-library/react';
import { ReactNode } from 'react';
import { ThemeProvider } from 'styled-components';
import defaultTheme from './styles/defaultTheme';

export default function renderWithThemeProvider(node:ReactNode) {
  const theme = defaultTheme;
  return render(<ThemeProvider theme={theme}>{node}</ThemeProvider>);
}
// Header.test.tsx
import { screen } from '@testing-library/react';
import Header from '.';
import renderWithThemeProvider from '../../renderWithThemeProvider';

function renderHeader() {
  renderWithThemeProvider(<Header />);
}

describe('Header', () => {
  beforeEach(() => {
    renderHeader();
  });

  it('renders logo', () => {
    const logo = screen.getByAltText(/logo/);
    expect(logo).toBeInTheDocument();
  });
  it('renders title', () => {
    const title = screen.getByText(/메가테라 푸드코트/);
    expect(title).toBeInTheDocument();
  });
  it('renders theme toggle button', () => {
    const toggleBtn = screen.getByRole('button');
    expect(toggleBtn).toBeInTheDocument();
  });
});
  • 실제 테스트 코드를 작성할 때, 미리 작성해둔 renderWith... 함수를 사용하여 중복을 제거할 수 있다.