インテグレーションテスト導入時のエラーと対応
はじめに
初めまして、株式会社Rehab for JAPAN でデイサービス向け介護請求ソフト レセプトの開発を担当している辻です。
レセプトのフロントエンドチームではテストコードが少なく、コード変更に伴うバグの懸念や、その修正作業への心理的負荷が大きいことが課題となっていました。
この課題に対する対応としてTesting Trophyにおけるインテグレーションテストを導入しました。
以下に、テスト導入時に発生したエラーとその対応内容を列挙します。
前提
構成は、Next.js + Jest + React Testing Library + MSW です。
Jest によるユニットテストは導入済で、すでに問題なく動作していました。
今回発生したエラーの多くは MSW のバージョンを2系に上げたことで発生したものでした。
公式ドキュメントのマイグレーションガイドを参照することで、以下に示したほとんどの問題は解決可能です。
使用ライブラリのバージョン
"@testing-library/jest-dom": "^6.5.0",
"@testing-library/react": "^16.0.1",
"@testing-library/user-event": "^14.5.2",
"@types/jest": "^29.5.12",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.1.2",
"msw": "^2.4.4",
1. ReferenceError が発生する
エラー内容
ReferenceError: TextEncoder is not defined
ReferenceError: Response is not defined
ReferenceError: TextDecoder is not defined
ReferenceError: Request is not defined
一般的な原因
ガイドラインに解説がありました。
This issue is caused by your environment not having the Node.js globals for one reason or another. This commonly happens in Jest because it intentionally robs you of Node.js globals and fails to re-add them in their entirely. As the result, you have to explicitly add them yourself.
この問題は、何らかの理由であなたの環境にNode.jsのグローバル変数が存在しないことが原因です。これは、Jestでよく発生します。Jestは意図的にNode.jsのグローバル変数を除去し、完全に再追加することに失敗するためです。その結果、これらを自分で明示的に追加しなければなりません。
解決方法
公式ガイドラインに従い、jest.polyfills.js を作成し、ポリフィルを追加しました。
undici という Node.js 用のHTTP/1.1クライアントライブラリをインストールする必要があります。
// jest.polyfills.js
import { createRequire } from 'module'
const require = createRequire(import.meta.url)
const { TextDecoder, TextEncoder } = require('node:util')
global.TextEncoder = TextEncoder
global.TextDecoder = TextDecoder
const { Request, Response } = require('undici')
global.Request = Request
global.Response = Response
// jest.config.js
module.exports = {
...
setupFiles: ['<rootDir>/jest.polyfills.js'],
}
2. msw/node が見つからない
エラー内容
Cannot find module 'msw/node' from '<path to test file>'
一般的な原因
ガイドラインに解説がありました。
This error is thrown by your test runner because JSDOM uses the browser export condition by default. This means that when you import any third-party packages, like MSW, JSDOM forces its browser export to be used as the entrypoint. This is incorrect and dangerous because JSDOM still runs in Node.js and cannot guarantee full browser compatibility by design
このエラーは、テストランナーによって発生しています。なぜなら、JSDOMはデフォルトでブラウザのエクスポート条件を使用するためです。つまり、MSWのようなサードパーティのパッケージをインポートする際、JSDOMはそのパッケージのブラウザ用のエクスポートをエントリーポイントとして強制的に使用します。これは不適切であり、危険です。というのも、JSDOMはNode.js上で動作しており、設計上、完全なブラウザ互換性を保証できないためです。
解決方法
公式ガイドラインに従い、jest.config.js を変更しました。
// jest.config.js
module.exports = {
...
testEnvironmentOptions: {
customExportConditions: [''],
},
}
3. toBeInTheDocument が見つからない
エラー内容
TypeError: expect(...).toBeInTheDocument is not a function
このエラーは、toBeInTheDocumentというマッチャー(テストの検証メソッド)が見つからないことを示しています。
expect(...) は正しく動作していますが、その後に続く .toBeInTheDocument() メソッドが認識されていません。
一般的な原因
このエラーが発生する主な理由は以下の通りです。
- @testing-library/jest-dom がプロジェクトに正しくインストールされていない。
- @testing-library/jest-dom がテストファイルで正しくインポートされていない。
- Jest の設定ファイルで @testing-library/jest-dom が正しくセットアップされていない。
解決方法
セットアップファイル内で@testing-library/jest-dom をインポートしました。
// jest.setup.js
import '@testing-library/jest-dom';
// jest.config.js
module.exports = {
...
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
}
おわりに
以上が、フロントエンドチームでインテグレーションテストを導入した際に発生したエラーと対応内容でした。
テストを導入したことでプロダクトコードに対する信頼性が増して、修正に対する心理的な負担も減ってきました。
今後もチームでトライアンドエラーを繰り返し、より堅牢なプロダクトを目指していきたいと思います。
Discussion