Next.js の getStaticProps 内で fetch を使っているページコンポーネントを Jest × React Testing Library × msw でテストしようとしたら ReferenceError: fetch is not defined になった
環境
- node.js
18.16.0 - Next.js
13.4.12 - React
18.2.0 - TypeScript
5.1.6 - jest
26.6.3 - @testing-library/react
14.0.0 - @testing-library/jest-dom
5.17.0 - msw
1.2.3
ReferenceError: fetch is not defined の発生
/src/pages/blog.tsx
type BlogPageProps = { posts: PostInterface[]; }; export default function BlogPage({ posts }: BlogPageProps) { // 略 }; export const getStaticProps: GetStaticProps = async () => { const res = await fetch(new URL(API_PATH)); const posts = await res.json(); return { props: { posts } }; };
node.js v18 からは node 環境でも fetch が使えるはずで、このページの画面の表示は問題なくできているがテストでは ReferenceError: fetch is not defined のエラーになってしまう状況
$ jest --env=jsdom --verbose
FAIL src/__tests__/BlogPage.test.tsx ReferenceError: fetch is not defined 23 | export const getStaticProps: GetStaticProps = async () => { > 24 | const res = await fetch(new URL(API_PATH)); | ^ 25 | const posts = await res.json(); 26 | 27 | return {
Jest で fetch を使うには polyfil が必要
fetchis not available in Node, which is where Jest is running your tests. Is it an experimental browser technology.
You will need to polyfill the behaviour if you want to make actual http calls, or mockfetchto simulate network requests.
cf. Fetch do not work on Jest · Issue #2071 · jestjs/jest · GitHub
Jest tests run in Node.js, although they execute your components that may use
window.fetch. How this works usually is testing environment polyfillsfetchfor you (i.e. withnode-fetch,whatwg-fetch, or any other compatible polyfills). Most of the frameworks like CRA come with that polyfill built-in, so you rarely pay attention that you need it.
cf. ReferenceError: fetch is not defined · Issue #686 · mswjs/msw · GitHub
polyfill を調べていると node-fetch, whatwg-fetch, cross-fetch の3つが有名っぽかった

node-fetch, cross-fetch は TypeScript で whatwg-fetch は JavaScript
node-fetch が最も利用されているが最終更新が 4年前だったので、最近も開発されている cross-fetch を使うことにした
$ npm i -D cross-fetch
テストファイルに cross-fetch を import する
/src/__tests__/BlogPage.test.tsx
import 'cross-fetch/polyfill'; // 略
テストファイルには import 'cross-fetch/polyfill'; を追加するだけで他には何も変更していないが、これでテストを実行すると問題なく fetch 部分が通り正しくテストが実行されるようになった
$ npm run test
…
PASS src/__tests__/BlogPage.text.tsx
node.js でも fetch が使えるようになっているはずだから大丈夫だろうと思っていたが、Jest 起因でエラーになってしまうのは予期してなかった。
polyfill の中身とかはちゃんと確認していないが Jest を使ったテストで ReferenceError: fetch is not defined になる場合は polyfill を使えば解決する。(本当はライブラリの中身をちゃんと確認したほうが良いのだが)
fetch が実行されるコンポーネントのテストの度に import 'cross-fetch/polyfill'; を書くのは少し面倒なので、テスト時に必ずインポートする設定ファイルのようにしてしまっても良いかもしれない
おわり
[参考]
- Fetch API - Web APIs | MDN
- Node.js fetch の内部の話 - from scratch
- Node.js に fetch がやってきた
- ReferenceError: fetch is not defined · Issue #686 · mswjs/msw · GitHub
- Fetch do not work on Jest · Issue #2071 · jestjs/jest · GitHub
- 【React,Jest, testing library】ReferenceError: fetch is not definedエラーの解消方法【vite,webpack】 - Engineering Tech Dojo
- cross-fetch vs node-fetch vs whatwg-fetch | npm trends


