JestでImport/Exportを使うとエラーになるときの対処法

IT

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に変換されます。

コメント

タイトルとURLをコピーしました