【Jest】画像ファイルやCSSのインポートに失敗する場合の対処法


ReactプロジェクトにJestを導入してテストコードを書いていたところ、エラーに遭遇して躓いたためその備忘録として。

事象

以下のようなSampleコンポーネントをJestでテストした時、エラーが発生しました。
エラーメッセージを確認すると画像ファイルの読み込みでシンタックスエラーが発生しているようです。

sample.tsx
import React from 'react'
import image from '../images/image-001.png'
import '../app.css'

const Sample = () => {
    return (
        <div className="sample">
            <span>Image File Test</span>
            <img src={image} alt="Image" />
        </div>
    )
}

export default Sample;
 FAIL  src/__test__/sample.test.tsx
  ● Test suite failed to run

    C:\Users\Application\src\images\image-001.png:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,
global,jest){�PNG

    SyntaxError: Invalid or unexpected token

    > 2 | import image from '../images/image-001.png';

また、同様の事象がCSSファイルのインポートでも発生します。

    C:\Users\Application\src\app.css:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,
global,jest){@import '~antd/lib/grid/style/index.css';

             ^

    SyntaxError: Invalid or unexpected token

      1 | import React from 'react'
      2 | import image from '../images/image-001.png'
    > 3 | import '../app.css'

原因

上のように画像やCSSをimportする処理は、WebPackによって解決されています。
JestはWebPackの機能を持っていないため、画像やCSSがインポートされた時にJavaScriptとして読み込こもうとしシンタックスエラーが発生します。

解決法

package.json、もしくはjest.config.jsに設定を加え、画像ファイルとCSSをモック化することで解決できます。

package.jsonの場合

package.json
{
  "jest": {
    "moduleNameMapper": {
      "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
      "\\.(css|scss)$": "<rootDir>/__mocks__/styleMock.js",
    }
  }
}

jest.config.jsの場合

jest.config.js
module.exports = {
  "moduleNameMapper": {
    "\\.(jpg|ico|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
    "\\.(css|scss)$": "<rootDir>/__mocks__/styleMock.js",
  },
}

次に、__mocks__フォルダ内に以下の2つのファイルを格納します。

__mocks__/styleMock.js
module.exports = 'test-file-stub';
__mocks__/fileMock.js
module.exports = ''; 

moduleNameMapperは渡された正規表現にマッチするモジュール名を持つ、画像やスタイルなどのリソースをスタブ化する設定です。
これによりインポートするモジュールが画像ファイルであった場合は代わりに__mocks__/fileMock.jsが、cssファイルであった場合は__mocks__/styleMock.jsが読み込まれるようになります。

参考

Using with webpack
Configuring Jest