Jestを用いたNext.jsのテストで環境変数を利用する
Next.jsは、Create React Appのように標準のテスト環境を提供していないため、開発者自身がテスト環境を用意する必要があります。
私は、JestとReact Testing Libraryを使ってこのブログをテストしていますが、環境変数を利用しているコンポーネントをテストする際に、Jestが環境変数をうまく読み込んでくれませんでした。
調べてみると、いくつか対処法が見つかったので、採用した方法とその他諸々をアウトプットしておきます。
- Can't access ENV vars defined in .env.test
- Misleading documentation: variables in .env and .env.test are not being loaded in test environment
最善策
setupEnv.ts
import { loadEnvConfig } from '@next/env'
export default async (): Promise<void> => {
loadEnvConfig(process.env.PWD || process.cwd())
}
jest.config.js
module.exports = {
globalSetup: '<rootDir>/setupEnv.ts',
}
テスト実行前に@next/env
のloadEnvConfig()
で環境変数ファイルを読み込みます。
loadEnvConfig()
の引数はprocess.env.PWD
だけでも動きますが、Windows環境ではprocess.env.PWD
がundefined
を返す可能性があるため、process.cwd()
も追加しています。
他の対処法
上記の方法が最善ですが、残りの対処法も紹介しておきます。
1. Next.jsのインスタンスを生成する
jest.setup.ts
import next from 'next'
next({})
jest.config.js
module.exports = {
setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
}
テストの前にNext.jsをインスタンス化してしまい、Next.js環境下でテストを実施する方法です。
この方法の良いところは、環境変数だけでなくfetch関数なども利用可能になる点でしょう。
ただ、インスタンスの作成にはビルドした.next
フォルダが必要となります。GitHub Actionsなどを用いてテストをCIで回す場合、毎回next build
が必要になります。
あと単純にテストが重くなります。
2. テスト用にdotenvを別途導入する
shell
yarn add --dev dotenv
jest.setup.ts
import dotenv from "dotenv";
dotenv.config({ path: ".env.local" });
jest.config.js
module.exports = {
setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
}
上で述べた欠点を改良した原始的な対処法です。
ただ、せっかくNext.jsがビルトインサポートしているdotenvを、テストのためだけに再インストールするのは気が乗りませんでした。