You need to enable JavaScript to run this app. Jest测试含动态import的Svelte组件时ES Module报错如何解决
优惠活动
大模型
产品
解决方案
定价
更多

Jest测试含动态import的Svelte组件时ES Module报错如何解决

Svelte组件动态导入场景的Jest测试解决方案

问题复现

场景说明

使用Jest为包含动态导入逻辑的Svelte组件编写测试,动态导入代码如下:

async function importComponent() {
    if (!dynamicComponent) {
      dynamicComponent= (await import('../Component')).Component;
    }
  }

package.json中Jest配置如下:

"jest": {
    "globals": {
      "ts-jest": {
        "isolatedModules": true,
        "tsConfig": "./tsconfig.json",
      }
    },
    "testEnvironment": "jsdom",
    "verbose": true,
    "transform": {
      "^.+\\.svelte$": [
        "svelte-jester",
        {
          "preprocess": true
        }
      ],
      "^.+\\.ts$": "ts-jest",
      "^.+\\.js$": "babel-jest"
    },
    "setupFilesAfterEnv": [
      "<rootDir>/setupTests.ts"
    ],
    "moduleFileExtensions": [
      "js",
      "ts",
      "svelte"
    ]
  }

触发报错的测试用例:

it('should open on click', async () => {
  const { getByRole } = render(ComponentUnderTest, { ...dummyProps });
  const loadComponentButton = getByRole('button');

  await fireEvent(loadComponentButton,  new MouseEvent('click', {
    bubbles: true,
    cancelable: true,
  }));
});

报错信息

触发的报错如下:

Error: You need to run with a version of node that supports ES Modules in the VM API.
使用的Node版本为v16.4.2,尝试过Jest官方ESM兼容方案后所有测试均报错,尝试过dynamic-import-node、@babel/plugin-syntax-dynamic-import、jest-next-dynamic库、直接Mock import语句等方案均无效。

报错原因

即使配置了jsdom测试环境,Jest本身仍运行在Node进程中,动态导入语法的解析依赖Node VM模块,低版本Jest对ESM动态导入的兼容存在缺陷,因此会触发该报错。

解决方案

将懒加载导入逻辑抽离到单独的中间代理文件中,通过Mock代理文件的方式避开原生import语句的兼容问题,同时还可以为加载逻辑编写独立测试用例,具体操作步骤如下:

  • 新建独立的加载逻辑代理文件,例如src/utils/component-loader.ts,将动态导入逻辑迁移到该文件:
// component-loader.ts
export async function importTargetComponent() {
  return (await import('../Component')).Component;
}
  • 修改原业务组件的引用逻辑,改为调用代理文件导出的方法:
import { importTargetComponent } from './utils/component-loader';

let dynamicComponent;
async function importComponent() {
  if (!dynamicComponent) {
    dynamicComponent = await importTargetComponent();
  }
}
  • 在测试文件中直接Mock代理文件的导出方法,自定义返回值即可:
// 测试文件顶部添加Mock逻辑
jest.mock('./utils/component-loader', () => ({
  // 可根据测试需要返回真实组件或Mock组件
  importTargetComponent: jest.fn().mockResolvedValue(jest.fn(() => ({ default: {} })))
}));

// 原有测试逻辑无需修改
it('should open on click', async () => {
  const { getByRole } = render(ComponentUnderTest, { ...dummyProps });
  const loadComponentButton = getByRole('button');

  await fireEvent(loadComponentButton,  new MouseEvent('click', {
    bubbles: true,
    cancelable: true,
  }));
});

这个方案对业务代码侵入性极低,同时完全避开了Jest ESM动态导入的兼容问题,测试可以正常运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 13:36:03