Jest「Cannot find module」エラーの原因と解決方法を完全解説

未分類

Jest「Cannot find module」エラーの原因と解決方法を完全解説

JavaScriptのテストフレームワークであるJestを使用していると、突然「Cannot find module」というエラーが発生することがあります。このエラーは初心者にとって非常に困惑させるもので、原因が一つではないため解決が難しい場合があります。本記事では、このエラーの原因から解決方法まで、段階的に詳しく解説します。

1. Jest「Cannot find module」エラーの原因

「Cannot find module」エラーは、Jestがテストファイルで参照されているモジュールを見つけられないときに発生します。このエラーの原因は複数存在し、それぞれ異なる解決方法が必要になります。

1-1. モジュールパスの指定が間違っている

最も一般的な原因は、import文で指定されたモジュールのパスが誤っている場合です。ファイルの相対パスを間違えたり、ファイル名のスペルミスがあったりすると、このエラーが発生します。例えば、実際には「utils.js」というファイルが存在するのに、「utils.ts」と指定してしまうようなケースです。

1-2. Jestの設定ファイルが不完全

Jest設定ファイル(jest.config.js)でモジュールパスの解決方法が正しく設定されていない場合があります。特に、TypeScriptやバベル(Babel)を使用している場合、設定が複雑になり、適切に設定されていないとモジュールが見つかりません。

1-3. node_modulesが正しくインストールされていない

package.jsonに依存関係が記載されているのに、実際には「node_modules」フォルダにそのパッケージがインストールされていないケースです。これは「npm install」や「yarn install」を実行していない、または実行後に依存関係が削除された場合に起こります。

1-4. moduleNameMapperの設定が不正

Jest設定で「moduleNameMapper」を使用してパスエイリアスを設定している場合、その設定が間違っていると「Cannot find module」エラーが発生します。例えば、@記号を使ったパスエイリアスの設定が不完全な場合などです。

1-5. TypeScriptの型定義ファイルが見つからない

TypeScriptプロジェクトで、型定義ファイル(.d.ts)や必要なTypeScript設定(tsconfig.json)が正しく設定されていない場合も、このエラーが発生する可能性があります。

2. 段階的な解決手順

「Cannot find module」エラーが発生した場合、以下の手順で段階的に原因を特定し、解決することができます。

ステップ1: エラーメッセージを詳しく確認

エラーメッセージには、どのファイルが見つからないのか、どこから参照されているのかが記載されています。例えば以下のようなメッセージが表示されます:

Cannot find module 'src/utils' from 'src/__tests__/app.test.js'

このメッセージから、「src/__tests__/app.test.js」というテストファイルが「src/utils」を参照しようとしていることが分かります。

ステップ2: ファイルの存在確認

参照されているファイルが実際に存在するかを確認します。ファイルシステムでそのパスにファイルが存在するか、ファイル名が正確かどうかを確認してください。

ステップ3: 相対パスの確認

相対パス(../や./など)が正しく指定されているかを確認します。親ディレクトリへの移動回数が多すぎたり、少なすぎたりしないか確認が必要です。

ステップ4: Jest設定ファイルの確認

jest.config.jsやpackage.jsonのjest設定セクションで、moduleNameMapperやtransformが正しく設定されているか確認します。

ステップ5: node_modulesの再インストール

外部パッケージが見つからない場合、node_modulesを削除して再インストールします。

ステップ6: キャッシュのクリア

Jestのキャッシュが古い情報を保持している可能性があるため、キャッシュをクリアします。

3. コード例による実装方法

3-1. 基本的なプロジェクト構成例

まず、一般的なプロジェクト構成を示します:

project/
├── src/
│   ├── utils.js
│   ├── app.js
│   └── __tests__/
│       └── app.test.js
├── package.json
├── jest.config.js
└── node_modules/

3-2. src/utils.js(テスト対象のモジュール)

// src/utils.js
export const add = (a, b) => {
  return a + b;
};

export const subtract = (a, b) => {
  return a - b;
};

export const multiply = (a, b) => {
  return a * b;
};

3-3. src/__tests__/app.test.js(正しいパスでのインポート)

// src/__tests__/app.test.js
import { add, subtract, multiply } from '../utils';

describe('Math utilities', () => {
  test('add関数が正しく計算される', () => {
    expect(add(2, 3)).toBe(5);
  });

  test('subtract関数が正しく計算される', () => {
    expect(subtract(5, 3)).toBe(2);
  });

  test('multiply関数が正しく計算される', () => {
    expect(multiply(4, 3)).toBe(12);
  });
});

上記の例では、テストファイルは「src/__tests__/」ディレクトリにあり、「utils.js」は親ディレクトリ(src/)にあるため、相対パスは「../utils」となります。

3-4. jest.config.js(基本的な設定)

// jest.config.js
module.exports = {
  testEnvironment: 'node',
  collectCoverageFrom: ['src/**/*.js'],
  testMatch: ['**/__tests__/**/*.js', '**/*.test.js'],
};

3-5. moduleNameMapperを使用した解決方法

パスエイリアスを使用する場合、jest.config.jsで以下のように設定します:

// jest.config.js(moduleNameMapperあり)
module.exports = {
  testEnvironment: 'node',
  moduleNameMapper: {
    '^@/(.*)$': '/src/$1',
  },
  collectCoverageFrom: ['src/**/*.js'],
  testMatch: ['**/__tests__/**/*.js', '**/*.test.js'],
};

この設定により、以下のようにインポートできます:

// src/__tests__/app.test.js
import { add } from '@/utils';

describe('Math utilities', () => {
  test('add関数が正しく計算される', () => {
    expect(add(2, 3)).toBe(5);
  });
});

3-6. TypeScriptを使用する場合の設定

TypeScriptプロジェクトの場合、以下の設定が必要です:

// jest.config.js(TypeScript対応)
module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  moduleNameMapper: {
    '^@/(.*)$': '/src/$1',
  },
  testMatch: ['**/__tests__/**/*.ts', '**/*.test.ts'],
};

さらに、tsconfig.jsonでパスマッピングを定義します:

// tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  }
}

3-7. package.jsonでの依存関係確認

{
  "name": "my-project",
  "version": "1.0.0",
  "devDependencies": {
    "jest": "^29.0.0",
    "ts-jest": "^29.0.0"
  }
}

3-8. npm/yarnコマンド実行例

# node_modulesを削除してキャッシュをクリア
rm -rf node_modules
rm package-lock.json

# 依存関係を再インストール
npm install

# Jestキャッシュをクリア
npx jest --clearCache

# テストを実行
npm test

4. よくある間違いと対策

4-1. ファイル拡張子を省略している

間違った例:

import { add } from '../utils'; // utils.jsではなくutils.tsが実際にある場合エラー

対策:ファイルが実際に存在するかを確認し、拡張子が正確か確認してください。Jestはデフォルトでいくつかの拡張子を自動的に解決しますが、設定によっては明示的に拡張子を指定する必要がある場合があります。

4-2. パス階層の誤り

間違った例:

// src/__tests__/app.test.jsから参照する場合
import { add } from './utils'; // 同じディレクトリを参照(間違い)
import { add } from '../utils'; // 正しい

対策:ファイルの配置を正確に把握し、正しい相対パスを指定してください。

4-3. moduleNameMapperとpackage.jsonのパスが一致していない

間違った例:

// jest.config.js
module.exports = {
  moduleNameMapper: {
    '^@/(.*)$': '/lib/$1', // libディレクトリを指定
  },
};

// tsconfig.json
{
  "paths": {
    "@/*": ["src/*"] // srcディレクトリを指定(不一致)
  }
}

対策:複数の設定ファイルを使用する場合、すべてのパスマッピングが一致していることを確認してください。

4-4. node_modulesが不完全な状態でテストを実行

間違った例:

npm install
# 途中で中断
npm test # エラーが発生

対策:インストールが完全に完了してから、テストを実行してください。

4-5. .gitignoreに不正なパターンがある

稀なケースですが、.gitignoreが正しく設定されていないと、必要なファイルがリポジトリに含まれず、クローン後にモジュールが見つからなくなる可能性があります。

対策:.gitignoreを確認し、必要なファイルが除外されていないことを確認してください。特に、tsconfig.jsonやjest.config.jsは追跡対象に含まれるべきです。

5. トラブルシューティングチェックリスト

以下のチェックリストに従って、順番に確認することで、ほとんどのケースで問題を解決できます:

  • ☐ エラーメッセージに記載されているファイルが実際に存在するか
  • ☐ ファイルのスペルと拡張子が正確か
  • ☐ 相対パス(../や./)が正しいか
  • ☐ jest.config.jsが存在し、正しく設定されているか
  • ☐ package.jsonのjest設定が正しいか
  • ☐ tsconfig.jsonが存在し、pathsが設定されているか(TypeScript使用時)
  • ☐ moduleNameMapperがtsconfig.jsonと一致しているか
  • ☐ node_modulesが完全にインストールされているか
  • ☐ 必要な依存関係(ts-jest、babel-jestなど)がインストールされているか
  • ☐ Jestのキャッシュをクリアしたか

6. まとめ

Jest「Cannot find module」エラーは、多くの場合、以下のいずれかの原因で発生します:

  • ファイルパスの指定が誤っている
  • Jest設定ファイルが不完全である
  • node_modulesが正しくインストールされていない
  • moduleNameMapperの設定が不正である
  • TypeScript関連の設定が不完全である

このエラーを解決するためには、以下の対策が効果的です:

  1. エラーメッセージを詳しく読み、どのモジュールが見つからないのかを特定する
  2. ファイルが実際に存在するか、パスが正確かを確認する
  3. jest.config.jsとtsconfig.jsonの設定が正しいか確認する
  4. node_modulesを再インストールし、Jestキャッシュをクリアする
  5. 段階的にテストを実行し、どの部分で問題が発生しているのかを特定する

本記事で紹介した方法を順に実施することで、ほとんどのケースで「Cannot find module」エラーを解決できます。同じエラーで困った場合は、本記事を参考に、段階的に原因を特定し、解決してください。

プログラミングは試行錯誤のプロセスです。エラーが発生した際は、焦らずにエラーメッセージを詳しく読み、原因を特定することが重要です。この習慣を身につけることで、将来的により複雑な問題にも対応できるようになります。

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