[Jest]TypeError: Cannot read property 'readFileSync' of null
Overview
Jestでテストを実行した際、以下のエラーに遭遇しましたか?
もしあなたがesmのパッケージを利用しているなら、私はその問題の緩和策を提示できるでしょう。
TypeError: Cannot read property 'readFileSync' of null
at fetch (node_modules/protobufjs/src/root.js:160:34)
at Root.load (node_modules/protobufjs/src/root.js:194:13)
at Root.loadSync (node_modules/protobufjs/src/root.js:235:17)
at Object.loadSync (node_modules/protobufjs/src/index-light.js:69:17)
at Object.<anonymous> (node_modules/@grpc/proto-loader/build/src/index.js:235:37)
Target reader
- 前述のエラーに遭遇した方。
Prerequisite
- Node.js v10.19.0
- esmパッケージを利用している
Body
Jestとesmの関係について少しだけ言及
- Node.js v10.19.0
- esmパッケージを利用している
Body
Jestとesmの関係について少しだけ言及
Jestはimport/exportの形式に執筆時点では対応していない。
つまりimport/exportの記述を可能にするesmとは相性が悪い。
その辺について知りたい場合は別記事を参照してください。
https://qiita.com/qrusadorz/items/f637953c0ada73483700#esm%E3%82%92%E5%B0%8E%E5%85%A5%E3%81%AB%E9%96%A2%E3%81%99%E3%82%8B%E6%B3%A8%E6%84%8F%E7%82%B9
esmをnodeコマンドで実行したり、サーバーレスのFunctionsで実行する分には問題ない。
それは私自身esmを実際に導入を完了しており、事実に基づいた発言である。
しかし、Jestだけはどうしてもだめだった
一応今回の問題はissueには上がっている。
https://github.com/standard-things/esm/issues/779
微妙に違うように見えるかもしれないが根本原因は一緒だと考えている。
恐らくこの問題は当分の間は解決されないだろうから、緩和策を模索した。
import文をあきらめる
人間引き際の判断が大事。幸いesmはrequireを混在して使ってもOKなので、エラーの発生する該当ソースはrequireのままにしておく。
本番ならそれだけでOKだが、Jestはesmの先にいるエラーが発生するパッケージのrequireを許してくれない
想像になるが、各テストのソースコード冒頭に置くconst requireEsm = require('esm')(module);
がrequireを置き換え、Jest環境下ではうまく行かないのだろう。
この考えのもと回避処理を作るとうまく行く。
まずはエラーが発生するテストコードの一行目を次のようにする。
global.requireJest = require; // ★esmが置き換える前のもとのrequireを保存しておく
// 通常はここが1行目で、esmのrequireを使用するだけでOK。
const requireEsm = require('esm')(module);
const { objectToArray } = requireEsm('../../utils/object')
ネーミングは重複しないなら何でもいいが、ここではrequireJestとして本来のrequireをglobalに保存する。
次にエラーが発生するimport部分に対応を入れる。
実際にエラーが発生したfirebase-adminのパッケージに対応した例を掲載する。
// import admin from 'firebase-admin'; // 残念ながらJestではエラーになる
const admin = global.requireJest ? requireJest('firebase-admin') : require('firebase-admin'); // for jest test
前述でglobal.requireJest
に保存したrequireがあるならそちらを利用し、ないなら本番環境なので通常のrequireを使用する。
これで本番でもJestでもどちらでも動くことが可能。
Conclusion
esmによりimport/exportが使用可能になり便利だが、最後にJestの落とし穴がある。
その箇所だけimportをあきらめれば完遂できるので、あきらめちゃだめだという話でした。
ちなみに私が一気に移行した際、firebaseAdmin.jsを参照しているテストが全てダメになった。
スタックトレースからはfirebaseAdmin.jsで発生したというのが不明のため、判明するのに時間かかりました。
(ちまちまスタブに置き換えてimport文一つ一つ探した)
Have a great day!
Author And Source
この問題について([Jest]TypeError: Cannot read property 'readFileSync' of null), 我々は、より多くの情報をここで見つけました https://qiita.com/qrusadorz/items/9950e8f52b20616c1583著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .