schedule2021-10-10

【TypeScript】JestでインポートしたモジュールがCannot find moduleとなるエラー

TypeScriptのjestで用意したテストで、自作のモジュールをインポートしようとするとCannot find moduleとなってしまう。

例として次のテストを実行してみる。

Login.test.ts
import LoginService from "@/app/Services/LoginService";
import auth from "@/Domain/Repositories/AuthRepository";

describe("LoginService", () => {
  it("LoginSuccess", () => {
    // ...
    expect(result).toBe('success');
  });
});

@/tsconfig.jsonで定義してある。エディタ(VSCode)のIDEではパスが通っているようでエラーは出ない。

実行した結果がこちら。 テストを実行したときだけパスが通らない。

● Test suite failed to run

    Cannot find module '@/app/Services/LoginService' from 'tests/app/Services/Login.spec.ts'

    > 1 | import LoginService from "@/app/Services/LoginService";
        | ^
      2 | import auth from "@/Domain/Repositories/AuthRepository";
      3 |
      4 | describe("LoginService", () => {

      at Resolver.resolveModule (node_modules/jest-resolve/build/resolver.js:322:11)
      at Object.<anonymous> (tests/app/Services/Login.spec.ts:1:1)

Test Suites: 1 failed, 1 passed, 2 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        17.456 s
Ran all test suites.

解決方法

テストはjest.config.js@/の定義が必要。

@/などtsconfig.jsonで定義してあるとVSCodeのIDEとアプリのコンパイルには成功する。

tsconfig.jsonのパスの定義

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

テストではtsconfig.jsonとは別にjest.config.js@/などのマッパーを定義する必要がある。

混乱しないようtsconfig.jsonと同じパスの定義をするといい。

jest.config.js
module.exports = {
  preset: "ts-jest",
  globals: {
    "ts-jest": {
      tsConfig: "tsconfig.json",
    },
  },
  roots: ["<rootDir>/"],
  testMatch: ["**/?(*.)+(spec|test).+(ts|tsx|js)"],
  transform: {
    "^.+\\.(ts|tsx)$": "ts-jest",
  },
  moduleNameMapper: {
    "^@/(.*)$": "<rootDir>/src/$1", // 追加
  },
};

以上でテストの実行時にパスが通った。