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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/50171412/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 05:23:17  来源:igfitidea点击:

Jest + Typescript + Absolute paths (baseUrl) gives error: Cannot find module

typescriptvisual-studio-codejestjscreate-react-appabsolute-path

提问by TheSoul

I am setting a configuration to run my tests in a create-react-app + typescript app (from which I have ejected). I am using jest + enzyme. In my tsconfig.json I have set baseUrl='./src'so I can use absolute paths when I import modules. For example this is a typical import statement in one of my files:

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

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

You can see that the path is absolute (from /src folder) and not relative. This works fine when I run in debug mode ( yarn start)

您可以看到路径是绝对路径(来自 /src 文件夹)而不是相对路径。当我在调试模式 ( yarn start)下运行时,这很好用

But when I run my test ( yarn test), I get this error:

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

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

So it looks like jest is not able to resolve this absolute path although I have set it up in my tsconfig.json. This is my tsconfig.json:

所以看起来 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"
  ]
}

Now I can see that there is a generated tsconfig.test.jsonat the root of my project. This is the ts configuration used for test. And here is its content:

现在我可以看到tsconfig.test.json在我的项目的根目录生成了一个。这是用于测试的 ts 配置。这是它的内容:

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

As you can see the "module" is commonjshere whereas in the default configuration it is esnext. Could this be one reason?

正如您所看到的,“模块”在commonjs这里,而在默认配置中它是esnext. 这可能是原因之一吗?

Has any one been able to unit test his typescript project with Jest and absolute path? or is this a known bug? Since I have ejected from default configuration, are there some settings to put in my webpack configuration?

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

Thanks for your input and suggestion.

感谢您的意见和建议。

回答by Antoine Laffargue

I was struggling with the same problem and actually it turns out that a simple change seems to do the trick.

我一直在为同样的问题苦苦挣扎,实际上结果证明一个简单的改变似乎可以解决问题。

I just updated the moduleDirectoriesfield in jest.config.js

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

Before

moduleDirectories: ['node_modules']

After

moduleDirectories: ['node_modules', 'src']

Hope it helps,
Antoine

希望它有帮助,
安托万

回答by jeznag

Here is how I got moduleNameMapper working.

这是我如何让 moduleNameMapper 工作的。

With the below config in my tsconfig:

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

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

Here's the moduleNameMapper:

这是 moduleNameMapper:

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

回答by Tim Osadchiy

As many here pointed out moduleNameMapperin jest.config.jsneeds to define paths specified in tsconfig.json. For example, if you have paths in tsconfig.jsondefined as follows

正如这里的许多人所指出的moduleNameMapperjest.config.js需要定义tsconfig.json. 例如,如果你有tsconfig.json如下定义的路径

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

then your jest.config.jsneeds to provide those paths in moduleNameMapperin the following format:

那么您jest.config.js需要以moduleNameMapper以下格式提供这些路径:

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

Having that we can improve our jest.config.jsto convert paths defined in tsconfig.jsonautomatically. Here is a Gist code snippetfor that:

有了它,我们可以改进我们jest.config.jstsconfig.json自动转换路径。这是一个Gist 代码片段

// 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('/*', '/');
        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)
};

回答by Necmttn

my solution was,

我的解决方案是,

  "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/"
    }
  }

回答by fsilva

I've using React with Typescript, I removed react-scripts-ts test --env=jsdomfrom npm testand added jest --watchas my default test, after I added jest.config.jsto my project following these instructions https://basarat.gitbooks.io/typescript/docs/testing/jest.html

我已经使用带有打字稿反应,我删除react-scripts-ts test --env=jsdomnpm test并添加jest --watch作为我的默认测试,之后我加入jest.config.js到我的项目按照以下说明https://basarat.gitbooks.io/typescript/docs/testing/jest.html

and I used the the configuration mentioned by @Antonie Laffargue (add/edit property moduleDirectories: ['node_modules', 'src']), it works perfectly.

我使用了@Antonie Laffargue 提到的配置(添加/编辑属性moduleDirectories: ['node_modules', 'src']),它工作得很好。

回答by Lattanzio

I had a similar problem. I hope this could help to spare time for some of you.

我有一个类似的问题。我希望这可以帮助你们中的一些人腾出时间。

My problem:

我的问题:

  • using create-react-app with typescript
  • using absolute paths (src/MyComp) to import components inside other components (e.g. App.tsx)
  • it was working on compile/run/build
  • it was notworking on test
  • 使用带有打字稿的 create-react-app
  • 使用绝对路径(src/MyComp)在其他组件(例如 App.tsx)中导入组件
  • 它正在编译/运行/构建
  • 没有进行测试

I found that the error was due to a different value of the NODE_PATH. So I set it on tests run.

我发现错误是由于 NODE_PATH 的不同值造成的。所以我在测试运行时设置了它。

I recreated the issue and the fix in here: https://github.com/alessandrodeste/...

我在这里重新创建了问题和修复:https://github.com/alessandrodeste/...

I'm not sure if this could bring side effects on tests. Let me know if you have feedback ;)

我不确定这是否会给测试带来副作用。如果您有反馈,请告诉我;)

回答by muk

ts-jest can resolve this problem perfectly!
https://kulshekhar.github.io/ts-jest/user/config/#paths-mapping
just modify jest.config.js like this:

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

回答by akaRem

You probably want moduleNameMapperfeature of jest config. It will map your custom import namespaces to real module locations.

您可能想要moduleNameMapper玩笑配置的功能。它将您的自定义导入命名空间映射到真实的模块位置。

see official documentation here:

在这里查看官方文档:

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

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