Jest を使ってテストを書いていると、次のようなエラーに遭遇することがあります。
ReferenceError: fetch is not defined
これは、Node.js 環境で実行される Jest が ブラウザの fetch API を持っていない ために発生するエラーです。React や Next.js などフロントエンド開発で fetch を使う機会は多いですが、そのままではテスト環境に fetch が存在せず落ちてしまいます。
本記事では、このエラーの原因を解説し、モックライブラリや設定で解決する方法を紹介します。
1. エラーが発生する背景
Jest はデフォルトで Node.js 環境で動作します。つまり、ブラウザのグローバル API(window
, fetch
, localStorage
など)は存在しません。次のようなシンプルなコンポーネントをテストしようとするとエラーになります。
// src/apiClient.js
export async function getData() {
const res = await fetch('/api/data')
return res.json()
}
// src/apiClient.test.js
import { getData } from './apiClient'
test('fetches data', async () => {
const data = await getData()
expect(data).toEqual({ foo: 'bar' })
})
実行結果:
ReferenceError: fetch is not defined
ブラウザでは当たり前に存在する fetch
が、Node.js では未定義であるためテストが失敗します。
2. 対処法1: whatwg-fetchを利用する
最もシンプルな解決策は、ポリフィルを追加して fetch を定義することです。
- パッケージをインストール
npm install --save-dev whatwg-fetch
- Jest のセットアップファイルでポリフィルを読み込む
// jest.setup.js
import 'whatwg-fetch'
- Jest 設定に setupFilesAfterEnv を追加
// jest.config.json
{
"setupFilesAfterEnv": ["<rootDir>/jest.setup.js"]
}
これでテスト実行時に fetch が定義され、API 呼び出しが実行可能になります。ただし、この方法では実際のリクエストがネットワークに飛ぶため、テストが遅くなったり外部依存が発生する可能性があります。
3. 対処法2: fetchをモックする
テストでは本物の API 通信を行わず、モックレスポンスを返す方が安定します。jest.fn() や msw (Mock Service Worker) を使う方法があります。
// apiClient.test.js
import { getData } from './apiClient'
beforeAll(() => {
global.fetch = jest.fn(() =>
Promise.resolve({
json: () => Promise.resolve({ foo: 'bar' })
})
)
})
test('fetches data', async () => {
const data = await getData()
expect(data).toEqual({ foo: 'bar' })
})
この方法なら、ネットワークに依存せず高速にテストできます。
msw を使った本格的モック
大規模プロジェクトでは msw を使うとより現実的なモックが可能です。
npm install msw --save-dev
// src/mocks/handlers.js
import { rest } from 'msw'
export const handlers = [
rest.get('/api/data', (req, res, ctx) => {
return res(ctx.json({ foo: 'bar' }))
})
]
// jest.setup.js
import { setupServer } from 'msw/node'
import { handlers } from './src/mocks/handlers'
const server = setupServer(...handlers)
beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
afterAll(() => server.close())
これにより、API レイヤーを完全にモックしつつ、fetch を使ったコードも透過的にテストできます。
4. 対処法3: Node.js v18以降のfetchサポートを利用
Node.js v18 以降では fetch が標準実装されています。プロジェクトが v18+ で動作する場合は、ポリフィルを追加せずともテストが通ることがあります。
node -v
# v18.12.0 以上なら標準で fetch 利用可
ただし、CI/CD 環境の Node.js バージョンが古いと再現しない可能性があるため、.nvmrc
や Volta でバージョン固定しておくことが推奨されます。
5. 実運用上の落とし穴とベストプラクティス
- ローカルでは動くがCIで落ちる問題
CI サーバーが Node.js v16 以下だと fetch がないため失敗します。バージョン統一が重要です。 - 実際のAPIを叩いてしまう問題
テスト環境が外部 API に依存すると不安定になります。msw などでモック化しましょう。 - global.fetch のリーク
テスト間で fetch のモックが残ると副作用が発生します。afterEach(() => jest.resetAllMocks())
でクリアしましょう。
afterEach(() => {
jest.resetAllMocks()
})
6. まとめ
Jest で「ReferenceError: fetch is not defined」エラーが出るのは、テスト環境で fetch が存在しないためです。解決するには:
- whatwg-fetch などでポリフィルを追加
- jest.fn() や msw を用いたモックで安定したテストを実現
- Node.js v18 以降なら標準 fetch を活用
- CI/CD 環境の Node.js バージョンを固定して再現性を担保
このエラーは初心者がよくハマるポイントですが、設定とモック戦略を整理すれば安定したテストが可能になります。
参考
- whatwg-fetch [https://github.com/github/fetch]
- msw Documentation [https://mswjs.io/docs/]
- Node.js fetch API [https://nodejs.org/api/globals.html#fetch]