Help us understand the problem. What is going on with this article?

jestでimport文を使うには

環境

・jest ^26.5.3
・babel-jest ^26.6.0
・@babel/core ^7.7.5
・@babel/preset-env ^7.7.6

babelrc
{
  "presets": [
    "@babel/preset-react",
    ["@babel/preset-env", {
      "targets": {
        "node": "current",
        "ie":11,
        "safari":9
      },
      "useBuiltIns": "usage",
      "corejs": 3,
      "modules": false
    }],
  ],

babelrcの初期設定がこんな感じになっています。

なぜimport/exportが使えないのか

上記設定のままだと、jestでimport/export(es6)文を実行することはできません。
jestでは require系のcommonjsしか使えないためです。
なので、 babelの処理で es6 -> commonjsへの変換を行う必要があります。

es6 -> commonjsに変換するには?

鍵を握るのは、 @babel/preset-envのoptionの modulesの項目です。
現在falseで設定しています。
falseだと、moduleの読み込み系の文を変換しない、つまりimport/export文はそのままなので
jestでエラーが出ているというわけです。

これを、 NODE_ENVでの切り替えを行い、 jestでテストしている時だけes6->commonjsに変換する
という風に設定します。

jest用のNODE_ENV

実はjestはデフォルトでtest用のNODE_ENV testが設定されています。

jestの中身
if (process.env.NODE_ENV == null) {
process.env.NODE_ENV = 'test'
}

なので、こちらで jest NODE_ENV=test と設定する必要はなく、
jest コマンドだけでbabelrcの処理を分岐させることが可能です。

babelrc
{
  "presets": [
    "@babel/preset-react",
    ["@babel/preset-env", {
      "targets": {
        "node": "current",
        "ie":11,
        "safari":9
      },
      "useBuiltIns": "usage",
      "corejs": 3,
      "modules": false
    }],
  ],
  "env": {
+   /* ここから下がjest用の処理 */
+    "test": {
+      "presets": [
+        "@babel/preset-react",
+        ["@babel/preset-env", {
+          "targets": {
+            "node": "current",
+            "ie":11,
+            "safari":9
+          },
+          "useBuiltIns": "usage",
+          "corejs": 3,
+          "modules": "cjs"
+        }]
+      ]
+    }
  }
}

NODE_ENVtestの場合は、 "modules": "cjs" に設定しています。
(cjsはcommonjsの略です)

jestがbabelでコンパイルされるようにする

上記作業だけではまだes6->commonjs変換を行うことはできません。
jest実行時にbabelでコンパイルするよう指示する必要があります。
jest実行時のconfigファイルはデフォルトではjest.config.jsですので、
jest.config.jsを作成します。

jest.con
module.exports = {
  verbose: true,
  transform: {
    '^.+\\.js$': 'babel-jest',
  },
  moduleFileExtensions: ['js'],
};

babel-jestパッケージをインストールします。
このパッケージがbabelでのコンパイルを行ってくれます。
https://www.npmjs.com/package/babel-jest

$ npm i -D babel-jest

以上でOK! 動作チェック

exporter.js
export async function addCalcFun(baseValue, addValue) {
  return baseValue + addValue;
}
importer.spec.js
import { callErrorFun } from './exporter'

describe('エラー', () => {
  it('通常のエラー', () => {
    expect(callErrorFun(2+2)).toBe(5)
  })
})

$ npx jest importer.spec.js

問題なく設定できていれば、上記の処理がうまく走ります🎉

参考資料

https://qiita.com/riversun/items/6c30a0d0897194677a37
https://tech.bitbank.cc/lets-test-by-jest/
https://qiita.com/hogesuke_1/items/8da7b63ff1d420b4253f#importexport%E6%A7%8B%E6%96%87%E3%82%92%E4%BD%BF%E3%81%88%E3%81%AA%E3%81%84%E5%95%8F%E9%A1%8C%E3%81%AE%E5%AF%BE%E5%87%A6

irico
新米フロントエンドエンジニアです。 得意なのはギターを弾くこと、苦手なことは運動です。 ゲーム(特にノベル物)が趣味です🎮
wiz_inc
Wizは、最新のIoTやICTサービスをお客様に届ける「ITの総合商社」です
http://012grp.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away