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 が必要
fetch
is 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 mockfetch
to 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 polyfillsfetch
for 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