개요
Jest + TypeScript
환경에서 RouterProvider
또는 ThemeProvider
를 테스트 하려고 한다.
- 실제 컴포넌트에서는 주로 Entry인
App
컴포넌트에 위 Provider
를 호출한다.
- 만약 테스트 코드를 작성할 때
Provider
없이 테스트 하려는 컴포넌트만 렌더링하게되면 실제 컴포넌트와 테스트 환경이 불일치하여 에러가 발생한다.
- 이를 해결하기 위해 helper 함수로
RouterProvider
와 ThemeProvider
를 함께 렌더링하는 로직을 함수로 추출해보자.
코드
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
로 컴포넌트를 감싸주어야 한다.
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>);
}
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...
함수를 사용하여 중복을 제거할 수 있다.