🃏

Next.js 12でJestの設定がかなり楽になった

2022/02/19に公開1

Next.js 12 における Jest サポートの強化

2/18 に Next.js 12.1 がリリースされました。

本バージョンの新機能として「next/jest プラグインを使った Zero-configuration Jest のサポート」が挙げられています。
この新機能自体は Next.js 12.0 の時点からベータ版として利用できるようにはなっていましたが、この度安定版がリリースされた形となります。

https://nextjs.org/blog/next-12-1#zero-configuration-jest-plugin

next/jest プラグインを使って Next.js アプリのテスト環境を構築する

next/jest プラグインを使う方法は以下の2点が挙げられます。
新規でアプリを作る際、時間がないときは1番の方法を取ってもいいでしょう。今回は2番の方法を紹介します。
(テンプレートが TS で書かれているのは地味に嬉しいポイント)

  1. create-next-app コマンドでテンプレートから新規アプリを作る
  2. next/jest プラグインを使用する方法

サンプルアプリのリポジトリはこちら。

https://github.com/miily8310s/nextjs-jest-example

必要なライブラリのインストール

Jest/React Testing Library を入れないことには何も始まらないのでまずインストールします。

npm install --save-dev jest @testing-library/react @testing-library/jest-dom
# or
yarn add -D jest @testing-library/react @testing-library/jest-dom

従来の方法では babel を使ってきましたが、next/jest プラグインでは使用しないため、インストール不要です。
また TS で Jest を使用する際は、ts-jest@types/jest のインストールが必要になりますが、next/jest プラグインを介す場合はこれらのインストールは不要です。

設定ファイルの作成

jest.config.js を作成します。Next.js 12 に搭載されたSWCの恩恵で簡潔な記述が可能になりました。
基本は公式で書かれている以下の書き方で問題ありません。

const nextJest = require("next/jest");

const createJestConfig = nextJest({
  // next.config.jsとテスト環境用の.envファイルが配置されたディレクトリをセット。基本は"./"で良い。
  dir: "./",
});

// Jestのカスタム設定を設置する場所。従来のプロパティはここで定義。
const customJestConfig = {
  // jest.setup.jsを作成する場合のみ定義。
  // setupFilesAfterEnv: ["<rootDir>/jest.setup.js"],
  moduleNameMapper: {
    // aliasを定義 (tsconfig.jsonのcompilerOptions>pathsの定義に合わせる)
    "^@/components/(.*)$": "<rootDir>/components/$1",
    "^@/pages/(.*)$": "<rootDir>/pages/$1",
  },
  testEnvironment: "jest-environment-jsdom",
};

// createJestConfigを定義することによって、本ファイルで定義された設定がNext.jsの設定に反映されます
module.exports = createJestConfig(customJestConfig);
今回定義した `tsconfig.json`
{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "baseUrl": ".",
    "paths": {
      "@/components/*": ["components/*"],
      "@/pages/*": ["pages/*"]
    }
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
  "exclude": ["node_modules"]
}

next/jest プラグインを使った場合の、jest.config.js のメリットを簡単にまとめておくと、以下の点が挙げられます。

  • transform の記載が不要(SWC が自動で transform してくれる)
  • css/scss ファイル/画像ファイルのモック化が自動で行われる
  • testPath から node_modules/.next フォルダがデフォルトで無視される
  • transform から node_modules フォルダがデフォルトで無視される

殆どのケースで設定しなければいけない内容を自動で処理してくれるおかげで、従来の babel を使用した場合と比べて、セットアップの負担の軽減が見て取れます。

テスト書いて動かしてみる

それでは、試しにコンポーネントのテストを書いてみましょう。書き方は従来どおりです。

components/Sample.tsx
export const Sample = () => {
  return (
    <main>
      <h1>Nextjs+Jestのサンプルサプリ</h1>
      <p>設定がすごく楽になりました。</p>
    </main>
  );
};
components/__tests__/Sample.spec.tsx
import { Sample } from "@/components/Sample";
import { render } from "@testing-library/react";

describe("Sampleコンポーネント", () => {
  test("should first", () => {
    const { getByText } = render(<Sample />);
    expect(getByText("Nextjs+Jestのサンプルサプリ")).toBeTruthy();
    expect(getByText("設定がすごく楽になりました。")).toBeTruthy();
  });
});

そして package.json の scripts も編集しておきましょう。

package.json
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
+   "test": "jest --watch",
    "lint": "next lint"
  },
}

これで yarn(npm run) test を叩ければ、テストが通ります 🎉。

トラブルがあったとき

ここまでメリットを紹介してきましたが、従来の babel を使用した方法から大きく変わる&登場したばかりの機能のため、まだトラブルがあったときのサポートが整ってるとは言い難いです。

Next.js はリポジトリに issues とは別に Discussion 機能が用意されており、next/jest プラグインに関するスレッドが用意されています。何かあればここを参考にしてみるのもいいでしょう。

https://github.com/vercel/next.js/discussions/31152

参考にしたページ

GitHubで編集を提案

Discussion

keisuke-333keisuke-333

参考にさせていただきました!ありがとうございます。

同じ内容でyarn testを実行すると下記のエラーになり実行できませんでした。

Test environment jest-environment-jsdom cannot be found. Make sure the testEnvironment configuration option points to an existing node module.

jestのv28から est-environment-jsdom を別途インストールする必要があるようです。
公式

余計なお世話であればすみません🙇‍♂️