본문 바로가기

Study

[Next 14] Next.js 프로젝트에 테스트 환경 구축하기 (jest, react-testing-library)

Next.js 프로젝트에 jest와 react-testing-library를 설치해서 테스트 환경을 구축해보려고 한다.

내 프로젝트 관련 버전 정보는 다음과 같다.

  • Next: 14.1.0
  • React: 18.2.0

1. 필요한 라이브러리 설치

npm install -D jest jest-environment-jsdom @testing-library/react @testing-library/dom @testing-library/jest-dom ts-node

 

패키지 역할 설치 이유
jest 테스트 러너 테스트 실행을 담당 (Test Runner)
jest-environment-jsdom 브라우저 환경을 흉내내는 테스트 환경 Next.js는 브라우저에서 동작하므로 JSDOM이 필요
@testing-library/react React 컴포넌트 테스트 React 컴포넌트를 렌더링하고 테스트하는 기능 제공
@testing-library/dom DOM 요소 테스트 HTML 요소 탐색 및 사용자 이벤트 테스트
@testing-library/jest-dom DOM 테스트 Matcher 추가 .toBeInTheDocument() 같은 Jest Matcher 추가
ts-node TypeScript 실행 지원 Jest 설정 파일을 TypeScript로 작성 가능

 

2. Jest 설정 파일 생성

npm init jest@latest

 

위 명령어를 통해 jest 설정 파일을 생성하려하면 여러 옵션값에 대한 질문을 하는데 나는 다음과 같이 설정해줬다.

  1. package.json에 test script 추가 할건지 ? Yes
  2. typescript로 설정파일을 생성 할건지? Yes
  3. 어떤 테스팅 환경을 사용할건지? jsdoma
    => 백엔드 코드, API 테스트를 원하면 node 선택
    => React, Next.js UI 테스트를 원하면 jsdom 선택
  4. 코드 커버리지 지표를 발행할건지? Yes
  5. 코드 커버리지 수집 시 어떤 도구를 사용할건지? v8
  6. Mock 데이터 자동 초기화를 할건지? Yes
    => 이전 테스트에서 사용한 Mock 정보가 다음 테스트에 영향을 줄 수 있어 자동으로 초기화 하도록 선택

해당 과정을 거치면 jest.config.ts 파일이 생성되는데 파일 안의 내용은 next.js 공식문서에 있는 내용으로 바꿔주었다.

// jest.config.ts

import type { Config } from 'jest'
import nextJest from 'next/jest.js'
 
const createJestConfig = nextJest({
  // Provide the path to your Next.js app to load next.config.js and .env files in your test environment
  dir: './',
})
 
// Add any custom config to be passed to Jest
const config: Config = {
  coverageProvider: 'v8',
  testEnvironment: 'jsdom',
  setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
}
 
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
export default createJestConfig(config)

 

공식문서에서는 주석 처리되어있던 setupFilesAfterEnv 속성은 Jest가 테스트 실행 전에 실행할 설정 파일을 지정하는 옵션으로
react-testing-library도 같이 사용할거기 때문에 주석을 해제해주고, jest.setup.ts 파일을 만들어 react-testing-library를 import 해주었다.

// jest.setup.ts
import '@testing-library/jest-dom';

3. (Optional) moduleNameMapper 설정 추가

만약 tsconfig.json에서 paths 설정을 사용하고 있다면, Jest는 typescript의 별칭 경로를 해석할 수 없으므로 moduleNameMapper 속성을 추가해준다.

// tsconfig.json
{
  "compilerOptions": {
    "baseUrl": "./",
    "paths": {
      "@/components/*": ["components/*"]
    }
  }
}
// jest.config.ts
moduleNameMapper: {
  '^@/components/(.*)$': '<rootDir>/components/$1',
}

 

이렇게하면 모든 설정은 끝이났다 🥳

이제 테스트를 만들어 정상적으로 테스팅 되는지 확인해보자.

테스트 만들기1 (React DOM UI 테스트)

import '@testing-library/jest-dom';
import { render, screen } from '@testing-library/react';
import Home from '@/app/page';

describe('Page', () => {
  it('renders a heading', () => {
    render(<Home />);

    const heading = screen.getByRole('heading');

    expect(heading).toBeInTheDocument();
  });
});

heading이라는 역할을 가진 요소가 Home 컴포넌트에 있는지 확인하는 간단한 테스트를 작성했다.

하지만 describe, it, expect 사용 할 때 에러가 발생했다. 이 오류는 Typescript가 Jest의 전역 테스트 함수(describe, it, expect)를 인식하지 못해서 발생하는 문제로 Jest의 타입 정의 패키지를 설치해주어야 한다.

npm i --save-dev @types/jest

 

그리고 tsconfig.json 파일에 jest 의 타입 정의를 포함시켜준다.

// tsconfig.json

{
  "compilerOptions": {
    "types": ["jest"]  // Jest의 타입 정의를 포함
  }
}

짜란

설정 후 에러가 사라진 것을 확인할 수 있다.

이제 npm run test 을 사용해 테스트 해보자!

💡특정 테스트 파일만 실행하는 방법
npm run test를 사용하면 모든 테스트 파일이 실행된다. 특정 테스트 파일만 실행하는 방법은 아래와 같다.
1. 파일 경로 지정
npm run test src/components/Button.test.tsx
2. 파일 이름 일부가 포함된 모든 테스트 파일 실행
npm run test — Button
3. jest 명령어로 파일 지정해서 실행
npx jest Button.test.tsx

Home.tsx에 h1 태그가 있을 경우 정상적으로 테스트가 성공되었고,
h1 태그를 제거하고 실행했을 땐 테스트가 실패해서 기대하는 결과와 같은걸 확인 할 수 있었다.

 

그런데.. 테스트 성공시에 아래와 같은 warning 메시지가 출력되었다.

🔥 Warning: React does not recognize the fetchPriority prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase fetchpriority instead. If you accidentally passed it from a parent component, remove it from the DOM element.

 

이 에러는 React에서는 DOM 속성을 자동으로 소문자로 변환해서 fetchpriority 으로 렌더링하는데
브라우저는 대소문자가 구분된 fetchPriority 를 기대하기 때문에 발생하는 에러라고 한다.

React 19 버전에서는 해결되었다는 글을 보았지만 나는 18버전을 쓰고 있기 때문에 해당 경고를 무시하기 위해서
jest.setup.ts에 해당 에러만 무시하는 코드를 추가해주었다.

jest.spyOn(console, 'error').mockImplementation((message) => {
  if (message.includes('fetchPriority')) {
    return;
  }
  console.error(message);
});

테스트 만들기2 (Typescript Utill 함수 테스트)

// add.ts
const add = (a: number, b: number): number => {
  return a + b;
};

export default add;
// add.test.ts
import add from '../add';

test('2+3=5', () => {
  expect(add(2, 3)).toBe(5);
});

아주 간단한 덧셈 함수를 생성해서 2+3은 5의 기댓값을 가진다는 테스트 함수를 작성했다.

 

utill 함수도 정상적으로 실행되는 것을 확인해 볼 수 있었다.

이렇게해서 Next.js에서 Jest와 React-testing-library를 사용해서 테스트 환경 구축이 완료되었다!

 

 

참고자료

- https://nextjs.org/docs/app/building-your-application/testing/jest