You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jest运行TypeScript测试遇意外令牌错误寻求解决方案

解决Jest测试中ES模块兼容问题

问题场景

开发目录结构:

.
├── README.md
└── business
    ├── jest.config.ts
    ├── nodeLayer
    │   └── db
    │       ├── README.md
    │       ├── dist
    │       │   └── db
    │       │       ├── index.js
    │       │       └── index.js.map
    │       │  
    │       ├── package-lock.json
    │       ├── package.json
    │       ├── src
    │            └── index.ts
    │       
    └── hoge1
        └── src
            ├── README.md
            ├── app
            │   └── app.ts
            ├── jest.config.ts
            ├── package-lock.json
            ├── package.json
            └── tests
                └── unit
                    └── get.test.ts

执行npm run test时出现以下错误:

➤ npm run test

> sync_app_info_to_aam_db@1.0.0 test
> npm run unit


> sync_app_info_to_aam_db@1.0.0 unit
> NODE_OPTIONS=--experimental-vm-modules jest --config jest.config.ts

 FAIL  tests/unit/get.test.ts
  ● Test suite failed to run

    Jest encountered an unexpected token

    Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.

    Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.

    By default "node_modules" folder is ignored by transformers.

    Here's what you can do:
     • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
     • If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/configuration
    For information about custom transformations, see:
    https://jestjs.io/docs/code-transformation

    Details:

    /xxxxxxxx/business/nodeLayer/db/dist/db/index.js:2
    import { createPool } from 'mysql2/promise';
    ^^^^^^

    SyntaxError: Cannot use import statement outside a module

       5 | import { ConnectionArguments, Db, SelectArguments } from '/opt/nodejs/dist/db';
       6 |
    >  7 | export const lambdaHandler = async (event: APIGatewayProxyEvent, context: Context): Promise<APIGatewayProxyResult> => {
         |              ^
       8 |     const client = new SecretsManagerClient({
       9 |         region: 'ap-northeast-1',
      10 |     });

      at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1495:14)
      at Object.<anonymous> (app/app.ts:7:14)
      at Object.<anonymous> (tests/unit/get.test.ts:4:15)

app.ts中的导入代码:

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import { ConnectionArguments, Db, SelectArguments } from '/opt/nodejs/dist/db';

当前jest.config.ts配置:

export default {
    preset: 'ts-jest',
    clearMocks: true,
    collectCoverage: true,
    coverageDirectory: 'coverage',
    coverageProvider: 'v8',
    testMatch: ['**/tests/unit/*.test.ts'],
    testPathIgnorePatterns: ['cf/.aws-sam/build'],
    moduleNameMapper: {
        '^/opt/nodejs/dist/db$': '<rootDir>/nodeLayer/db/dist/db',
    },
};

问题核心:CommonJS模式下Jest无法处理dist目录中ES模块格式的import语句,需要切换到ES模块兼容配置。

解决方案

1. 标记项目为ES模块

在hoge1/src/package.json中添加"type": "module":

{
  "name": "sync_app_info_to_aam_db",
  "version": "1.0.0",
  "type": "module",
  // 其他原有配置...
}

2. 更新Jest配置

修改hoge1/src/jest.config.ts,适配ES模块:

export default {
  // 使用ts-jest的ES模块预设
  preset: 'ts-jest/presets/default-esm',
  clearMocks: true,
  collectCoverage: true,
  coverageDirectory: 'coverage',
  coverageProvider: 'v8',
  testMatch: ['**/tests/unit/*.test.ts'],
  testPathIgnorePatterns: ['cf/.aws-sam/build'],
  moduleNameMapper: {
    // 直接导入TypeScript源文件,避免处理编译后的ES模块文件
    '^/opt/nodejs/dist/db$': '<rootDir>/../nodeLayer/db/src/index.ts',
  },
  // 告知Jest将.ts文件视为ES模块
  extensionsToTreatAsEsm: ['.ts'],
  moduleFileExtensions: ['ts', 'js'],
  // 配置ts-jest以ES模块模式转译TypeScript
  transform: {
    '^.+\\.tsx?$': ['ts-jest', { useESM: true }],
  },
};

3. 调整TypeScript配置(若存在)

确保hoge1/src/tsconfig.json中启用ES模块相关配置:

{
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "NodeNext",
    "target": "ES6",
    // 其他原有配置...
  }
}

4. 修正导入注释(可选)

因为现在直接导入源文件,TypeScript可以识别类型,可移除@ts-ignore注释:

import { ConnectionArguments, Db, SelectArguments } from '/opt/nodejs/dist/db';

原理说明

  • 标记"type": "module"后,Node.js和Jest会默认以ES模块模式加载文件
  • 使用ts-jest/presets/default-esm预设,让ts-jest处理TypeScript到ES模块的转译
  • 直接导入TypeScript源文件,跳过dist目录中已编译的ES模块文件,避免Jest以CommonJS模式加载时出现语法错误

内容的提问来源于stack exchange,提问作者kyoshida

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 18:05:01