Jest + Typescript +绝对路径(baseUrl)给出错误:找不到模块

时间:2018-05-04 09:16:58

标签: typescript visual-studio-code jestjs create-react-app absolute-path

我正在设置配置以在create-react-app + typescript应用程序(从中弹出)中运行我的测试。我正在使用jest +酶。在我的tsconfig.json中,我设置了baseUrl='./src',因此在导入模块时我可以使用绝对路径。例如,这是我的一个文件中的典型import语句:

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

您可以看到路径是绝对路径(来自/ src文件夹)而不是相对路径。 当我在调试模式(yarn start

中运行时,这可以正常工作

但是当我运行我的测试(yarn test)时,我收到此错误:

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

所以看起来jest无法解析这个绝对路径,尽管我已经在我的tsconfig.json中设置了它。这是我的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。这可能是一个原因吗?

有没有人能够用Jest和绝对路径对他的打字稿项目进行单元测试?或者这是一个已知的错误?由于我从默认配置中退出,是否有一些设置要放入我的webpack配置中?

感谢您的意见和建议。

13 个答案:

答案 0 :(得分:4)

这对我有用:

npm i -D jest typescript
npm i -D ts-jest @types/jest
npx ts-jest config:init

然后在 jest.config.js 中,这是我的设置

module.exports = {
  preset: "ts-jest",
  testEnvironment: "node",
  modulePaths: ["node_modules", "<rootDir>/src"],
};

就我而言,我在 paths 中没有任何 tsconfig.json,但我将 baseUrl 设置为 src

答案 1 :(得分:3)

我一直在同一个问题上挣扎,实际上事实证明,简单的更改似乎可以解决问题。

我刚刚更新了moduleDirectories中的jest.config.js字段

之前

moduleDirectories: ['node_modules']

之后

moduleDirectories: ['node_modules', 'src']

希望有帮助,
安托万

答案 2 :(得分:2)

这是我如何使moduleNameMapper工作的。

在我的tsconfig中使用以下配置:

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

这是moduleNameMapper:

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

答案 3 :(得分:2)

我的解决方法是

body {
  max-width: 40rem;
  padding: 0 1rem;
  font-size: 125%;
  line-height: 1.5;
  margin: 1.5rem auto;
  font-family: "Lato", Arial, sans-serif;
  font-size: 16px;
}

* {
  color: inherit;
  margin: 0;
}

[role="tablist"] {
  padding: 0;
}

[role="tablist"] li,
[role="tablist"] b {
  display: inline-block;
}

[role="tablist"] b {
  text-decoration: none;
  padding: 0.5rem 1em;
  cursor: pointer;
}

[role="tablist"] a {
  text-decoration: none;
  padding-left: 0.2rem;
  word-wrap: break-word;
}

[role="tablist"] [aria-selected] {
  border: 2px solid;
  background: #fff;
  border-bottom: 0;
  position: relative;
  top: 2px;
}

[role="tabpanel"] {
  border: 2px solid;
  padding: 1.5rem;
}

[role="tabpanel"] * + * {
  margin-top: 0.75rem;
}

*:focus {
  outline: none;
  box-shadow: inset 0 0 0 4px lightBlue;
}

@media (max-width: 550px) {
  [role="tablist"] li,
  [role="tablist"] b {
    display: block;
    position: static;
  }

  [role="tablist"] b {
    border: 2px solid #222 !important;
  }

  [role="tablist"] li + li b {
    border-top: 0 !important;
  }

  [role="tablist"] [aria-selected] {
    position: static;
  }

  [role="tablist"] [aria-selected]::after {
    content: "\0020⬅";
  }

  [role="tabpanel"] {
    border-top: 0;
  }
}

section a {
  color: rgb(66, 133, 244);
}

答案 4 :(得分:1)

我已将React与Typescript一起使用,在按照以下说明将react-scripts-ts test --env=jsdom添加到项目后,我从npm test中删除了jest --watch并添加了jest.config.js作为默认测试https://basarat.gitbooks.io/typescript/docs/testing/jest.html

并且我使用了@Antonie Laffargue提到的配置(添加/编辑属性moduleDirectories: ['node_modules', 'src']),它运行完美。

答案 5 :(得分:1)

我有类似的问题。我希望这可以帮助您节省一些时间。

我的问题:

  • 使用带有打字稿的create-react-app
  • 使用绝对路径(src / MyComp)在其他组件(例如App.tsx)中导入组件
  • 它正在编译/运行/构建
  • 不是正在测试

我发现错误是由于NODE_PATH的值不同所致。所以我将其设置为测试运行。

我在此处重新创建了问题和解决方法:https://github.com/alessandrodeste/...

我不确定这是否会对测试产生副作用。让我知道您是否有反馈意见;)

答案 6 :(得分:1)

对于那些使用绝对路径但不使用命名映射的人,这对我有用:

# jsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
  }
}

# jest.config.js
const config = {
  moduleDirectories: ['node_modules', '<rootDir>'],
};

答案 7 :(得分:0)

您可能需要jest配置的moduleNameMapper功能。 它会将您的自定义导入名称空间映射到实际模块位置。

请参阅此处的官方文档:

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

答案 8 :(得分:0)

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)
    }

答案 9 :(得分:0)

这里许多人指出moduleNameMapper中的jest.config.js需要定义tsconfig.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)
};

答案 10 :(得分:0)

package.json 的jest配置中添加以下内容为我解决了此问题。

 "moduleDirectories": [
  "node_modules",
  "src"
]

答案 11 :(得分:0)

如果您在 monorepo 中遇到这种情况,这里是为我解决问题的方法:

内部jest.config.js

roots: ["<rootDir>packages"],
moduleNameMapper: {
  '@monopre/(.+)$': '<rootDir>packages/$1/src',
},

假设您在 tsconfig.json

"paths": {
  "@monopre/*": ["packages/*/src"],
}

答案 12 :(得分:0)

使用 Svelte Kit,我的解决方案是:

import { readFileSync } from 'fs';
import pkg from 'ts-jest/utils/index.js';
const { pathsToModuleNameMapper } = pkg;

const { compilerOptions } = JSON.parse(readFileSync('./tsconfig.json'))

export default {
    preset: 'ts-jest',
    testEnvironment: 'node',
    testMatch: ['<rootDir>/**/*.test.ts'],
    testPathIgnorePatterns: ['/node_modules/'],
    coverageDirectory: './coverage',
    coveragePathIgnorePatterns: ['node_modules'],
    globals: { 'ts-jest': { diagnostics: false } },
    transform: {},
    moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: '<rootDir>/' }),
}