Jest,ts-jest,带有ES模块导入的TypeScript:找不到模块

25
我在使用TypeScript项目时,使用ES模块和import语法的jest测试不顺利。最初项目是使用commonjs编写的,jest测试可以正常运行。但是后来为了学习目的,我决定切换到ES模块,但jest不开心 ヽ(`Д´)ノ。 我正在使用的工具有: typescript, jest, ts-jest 问题出现在import语法上。 以下是我尝试过的代码。
//  projectRoot/src/app.ts

export default someFunction = (): void => {
   // some code
}
如果
// projectRoot/__tests__/app.test.ts

import someFunction from '../src/app';   // without file extension

/* This execute perfectly fine */
但是
// projectRoot/__tests__/app.test.ts

import someFunction from '../src/app.ts'   // with .ts

/*
● Test suite failed to run

   __tests__/app.test.ts:1:25 - error TS2691: An import path cannot end with a '.ts' extension. Consider importing '../src/app' instead.

    1 import information from '../src/app.ts';
*/

并且

// projectRoot/__tests__/app.test.ts

import someFunction from '../src/app.js';   // with .js

/*
● Test suite failed to run

    Cannot find module '../src/app.js' from '__tests__/app.test.ts'
*/
如上例,jest(或者可能是ts-jest?)对于使用扩展名(这对于ES模块是必需的)导入模块时不太友好。 我在网上进行了一些搜索,但似乎jest 文档 对于ES模块并不支持。同样,ts-jest也是如此,根据这个 问题

我的项目结构:

/projectRoot
 ├── /src/app.ts
 ├── /__tests__/app.test.ts

package.json文件中有一个值"type": "module"

tsconfig.json:

{
  "compilerOptions": {
     "target": "ES2015",
     "module": "ESNEXT",
     "outDir": "./build",
     "strict": true,
     "moduleResolution": "node",
     "esModuleInterop": true,
     "skipLibCheck": true,
     "forceConsistentCasingInFileNames": true
  },
  "include": ["./src"],
  "exclude": ["node_modules", "**/*.test.ts"]
}

jest.config.js

export default {
    "roots": [
      //"<rootDir>/src"
      "<rootDir>"
    ],
    "testMatch": [
      "**/__tests__/**/*.+(ts|tsx|js)",
      "**/?(*.)+(spec|test).+(ts|tsx|js)"
    ],
    "transform": {
      "^.+\\.(ts|tsx)$": "ts-jest"
    },
    "preset": "ts-jest",
    "testEnvironment": 'node'
  }

请帮忙。谢谢。


你有 GitHub 仓库的链接或其他吗? - geodoo
嗨@geodoo,这是我的存储库[https://github.com/koonfoon/ts-jest-code-test]。 - koonfoon
2
有人解决了这个问题吗? - raf
@Rafael,请看下面的答案。希望能有所帮助。 - analytical_prat
1个回答

28

在下面的导入中

// projectRoot/__tests__/app.test.ts

import someFunction from '../src/app.js';   // with .js

jest.config.js 文件中,可以通过以下配置来使用 ts-jest:

module.exports = {
  //... // your previous configurations
  extensionsToTreatAsEsm: ['.ts'],
  globals: {
    'ts-jest': {
      //... // your other configurations here
      useESM: true,
    },
  },
  moduleNameMapper: {
    '^(\\.{1,2}/.*)\\.js$': '$1',
  }

这个配置的源代码可以在 ts-jest 的文档页面上找到:ESM-Support

以下是一些示例代码:

// components_ts.ts
export add(x: number, y: number): number {
    return x + y;
}
// render_ts.ts
import * as ComponentsTS from './components_ts.js'; // <-- Extension is JS

export function addedNumbers(): number {
    let addedNumbers: number = ComponentsTS.add(1, 2);
    return addedNumbers;
}
// render_ts.test.ts
import * as RenderTS from '../ts_files/render_ts';

it ('Test addNumbers function', () => {
    expect(RenderTS.addedNumbers()).toBe(3);
});

使用 npm jest 命令来运行此操作。


1
moduleNameMapper是我缺失的部分。谢谢。 - Thirdshift
1
这是一个很好的答案。我将moduleNameMapper配置为'^(\.{1,2}/.+)\.js$': '$1',它使用+而不是*。 - jjangga
谢谢这个!我都快发疯了。添加moduleNameMapper对我也起了作用。 - Antonio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接