web-dev-qa-db-ja.com

Jest + TypeScript +絶対パス(baseUrl)でエラーが発生する:モジュールが見つかりません

Create-react-app + TypeScriptアプリでテストを実行するように構成を設定しています(from from ejected)。私はjest +酵素を使用しています。 tsconfig.jsonでbaseUrl='./src'を設定したため、モジュールをインポートするときに絶対パスを使用できます。たとえば、これは私のファイルの1つにある典型的なimportステートメントです。

import LayoutFlexBoxItem from 'framework/components/ui/LayoutFlexBoxItem';

パスは絶対パス(/ srcフォルダーから)であり、相対パスではないことがわかります。これは、デバッグモード(yarn start)で実行すると正常に機能します

しかし、テスト(yarn test)を実行すると、次のエラーが表示されます。

 Cannot find module 'framework/components/Navigation' from 'index.tsx'

そのため、tsconfig.jsonでjestを設定しましたが、jestはこの絶対パスを解決できないようです。これは私のtsconfig.jsonです:

{
  "compilerOptions": {
    "outDir": "dist",
    "module": "esnext",
    "target": "es5",
    "lib": ["es6", "dom"],
    "sourceMap": true,
    "allowJs": true,
    "jsx": "react",
    "moduleResolution": "node",
    "rootDir": "src",
    "forceConsistentCasingInFileNames": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "suppressImplicitAnyIndexErrors": true,
    "noUnusedLocals": true,
    "baseUrl": "./src"    
  },
  "exclude": [
    "node_modules",
    "build",
    "dist",
    "config",    
    "scripts",
    "acceptance-tests",
    "webpack",
    "jest",
    "src/setupTests.ts"
  ]
}

これで、プロジェクトのルートに生成されたtsconfig.test.jsonがあることがわかります。これは、テストに使用されるts構成です。そして、その内容は次のとおりです。

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "module": "commonjs"
  }
}

ご覧のとおり、ここでは「モジュール」はcommonjsですが、デフォルトの構成ではesnextです。これが1つの理由でしょうか?

Jestと絶対パスを使用してTypeScriptプロジェクトを単体テストできる人はいますか?またはこれは既知のバグですか?デフォルトの構成から削除したので、webpackの構成に入れるべき設定はありますか?

ご意見とご提案をお寄せいただきありがとうございます。

10
TheSoul

私は同じ問題に苦しんでいましたが、実際には簡単な変更でうまくいくようです。

jest.config.jsmoduleDirectoriesフィールドを更新しました

moduleDirectories: ['node_modules']

moduleDirectories: ['node_modules', 'src']

それが役に立てば幸い、
アントワーヌ

6

ModuleNameMapperがどのように機能するかを以下に示します。

私のtsconfigに以下の設定を使用します:

    "paths": {
      "@App/*": [
        "src/*"
      ],
      "@Shared/*": [
        "src/Shared/*"
      ]
    },

ModuleNameMapperは次のとおりです。

"moduleNameMapper": {
  "@App/(.*)": "<rootDir>/src/$1",
  "@Shared/(.*)": "<rootDir>/src/Shared/$1"
}
5
jeznag

私の解決策は、

  "jest": {
    "moduleDirectories": [
      "node_modules",
      "src"
    ],
    "moduleFileExtensions": [
      "js",
      "json",
      "ts"
    ],
    "roots": [
      "src"
    ],
    "testRegex": ".spec.ts$",
    "transform": {
      "^.+\\.(t|j)s$": "ts-jest"
    },
    "coverageDirectory": "../coverage",
    "testEnvironment": "node",
    "moduleNameMapper": {
      "src/(.*)": "<rootDir>/src/$1"
    }
  }
4
Necmttn

TypeScriptでReactを使用しています。react-scripts-ts test --env=jsdom from npm testおよび追加jest --watchを追加した後のデフォルトのテストとしてjest.config.jsこれらの指示に従って私のプロジェクトに https://basarat.gitbooks.io/TypeScript/docs/testing/jest.html

そして、@ Antonie Laffargueが言及している構成を使用しました(プロパティmoduleDirectories: ['node_modules', 'src'])、それは完全に動作します。

3
fsilva

ここで多くの人が指摘したように、jest.config.jsmoduleNameMappertsconfig.jsonで指定されたパスを定義する必要があります。たとえば、次のように定義されたtsconfig.jsonにパスがある場合

// tsconfig.json
{
 ...
 "baseUrl": "src",
 "paths": {
    "@alias/*": [ 'path/to/alias/*' ]
 }
 ...
}

jest.config.jsは、これらのパスをmoduleNameMapperで次の形式で提供する必要があります。

// jest.config.js
module.exports = {
    'roots': [
        '<rootDir>/src'
    ],
    'transform': {
        '^.+\\.tsx?$': 'ts-jest'
    },
    'moduleNameMapper': {
         '@alias/(.*)': '<rootDir>/src/path/to/alias/$1'
    }
};

jest.config.jsを改善して、tsconfig.jsonで定義されたパスを自動的に変換できます。以下が Gist code snippet です:

// jest.config.js

function makeModuleNameMapper(srcPath, tsconfigPath) {
    // Get paths from tsconfig
    const {paths} = require(tsconfigPath).compilerOptions;

    const aliases = {};

    // Iterate over paths and convert them into moduleNameMapper format
    Object.keys(paths).forEach((item) => {
        const key = item.replace('/*', '/(.*)');
        const path = paths[item][0].replace('/*', '/$1');
        aliases[key] = srcPath + '/' + path;
    });
    return aliases;
}

const TS_CONFIG_PATH = './tsconfig.json';
const SRC_PATH = '<rootDir>/src';

module.exports = {
    'roots': [
        SRC_PATH
    ],
    'transform': {
        '^.+\\.tsx?$': 'ts-jest'
    },
    'moduleNameMapper': makeModuleNameMapper(SRC_PATH, TS_CONFIG_PATH)
};
2
Tim Osadchiy

同様の問題がありました。これが皆さんの時間を割くのに役立つことを願っています。

私の問題:

  • typeScriptでcreate-react-appを使用する
  • 絶対パス(src/MyComp)を使用して、他のコンポーネント(例:App.tsx)内のコンポーネントをインポートする
  • コンパイル/実行/ビルドに取り組んでいました
  • テスト中だったnot

エラーはNODE_PATHの異なる値が原因であることがわかりました。そのため、テスト実行時に設定しました。

ここで問題と修正を再現しました: https://github.com/alessandrodeste/...

これがテストに副作用をもたらすかどうかはわかりません。フィードバックがあれば教えてください;)

1
Lattanzio

ts-jestはこの問題を完全に解決できます!
https://kulshekhar.github.io/ts-jest/user/config/#paths-mapping
jest.config.jsを次のように変更します。

    const { pathsToModuleNameMapper } = require('ts-jest/utils');
    const { compilerOptions } = require('./tsconfig.json');
    module.exports = {
        preset: 'ts-jest',
        moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths)
    }
0
muk

おそらくjest configのmoduleNameMapper機能が必要でしょう。カスタムインポート名前空間を実際のモジュールの場所にマップします。

こちらの公式ドキュメントをご覧ください。

https://facebook.github.io/jest/docs/en/configuration.html#modulenamemapper-object-string-string

0
akaRem