import/exportしたモジュールをjestで使うとエラーになる
jestを利用して、コードのテストをしようとしたところ以下のようなエラーメッセージが表示されました。
FAIL test/test.spec.js
● Test suite failed to run
Jest encountered an unexpected token
Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.
Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.
By default "node_modules" folder is ignored by transformers.
Here's what you can do:
• If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
• If you need a custom transformation specify a "transform" option in your config.
• If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/configuration
For information about custom transformations, see:
https://jestjs.io/docs/code-transformation
Details:
/Users/User/Dev/sample/js/sample.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export default class Sample {
^^^^^^
SyntaxError: Unexpected token 'export'
原因
jestの公式サイトを確認すると、ESMで書かれたimport/exportを使った構文は、CommonJSのようにmodule.export/require(“)の形式に変換されている必要があるようです。
JestはNode上で動作するため、ESモジュールはCommonJSモジュールにトランスパイルされている必要があります。
https://jestjs.io/ja/docs/next/webpack
javascriptではモジュール仕様、読み込みの手法がいくつか存在します。ESMやCommonJSというのはその方法の一つです。
ESM(ES Modules)
- モジュールの書き出しにexport、読み込みにimportを使う(ES6というバージョンからモジュールが利用できるようになった)
- ChromやSafari等のブラウザでサポートされている
具体例
書き出し側
export function sayHello(name) {
alert('Hello'+name);
}
読み込み側
import {sayHello} from "./module";
sayHello();
CJS(CommonJS)
- モジュールの書き出しにmodule.export、読み込みにrequireを使う
- node.js(サーバーサイド)向けの書き方
具体例
書き出し側
module.exports = function() {
console.log('Hello World!!');
}
読み込み側
const helloWorldModule = require('./module.js');
helloWorldModule();
解決方法
babelを使って、テストを実行するときにCJSに変換して実行されるようにします。
babelをインストールします。
npm install --save-dev @babel/core @babel/preset-env
次にbabel.config.jsを作成します。babel.config.jsが無い場合はpackage.jsなどと同じ階層にbabel.config.jsを作成し、以下の内容で保存します。
module.exports = {
presets: [
[
'@babel/preset-env',
{
'modules': 'false',
'useBuiltIns': 'usage',
'targets': '> 0.25%, not dead',
}
]
],
env: {
test: {
presets: [['@babel/preset-env', {targets: {node: 'current'}}]],
},
},
};
これで@babel/preset-envによってテストを実行する際にコードがCommonJSに変換されます。
コメント