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

如何为Jest中通过vm.runInContext加载的代码收集覆盖率?

解决Jest覆盖率为空的问题

你的问题出在用vm.runInContext直接执行代码时,V8覆盖率工具无法追踪到这些脚本的执行情况——Jest的V8覆盖率是基于通过其模块加载机制处理的文件,而手动读文件用VM执行的代码不在这个追踪范围内。以下是两种可行的解决办法:

方法一:切换到Babel覆盖率提供商并调整代码加载方式

这种方法通过Babel将无模块的全局代码转换为可被Jest识别的模块,同时保留全局挂载的逻辑。

步骤1:安装依赖

npm install --save-dev @babel/core @babel/preset-env babel-jest

步骤2:修改jest.config.js

将覆盖率提供商切换为babel,并启用babel-jest转换:

module.exports = {
  clearMocks: true,
  collectCoverage: true,
  collectCoverageFrom: [
    "src/**/*.js",
  ],
  coverageDirectory: "coverage",
  coverageProvider: "babel", // 切换到babel覆盖率
  testEnvironment: "./jest.env.js",
  transform: {
    "^.+\\.js$": "babel-jest" // 用babel处理所有JS文件
  },
};

步骤3:创建Babel配置文件(.babelrc)

添加预设和插件,将全局函数自动转为模块导出:

{
  "presets": ["@babel/preset-env"],
  "plugins": [
    // 把顶级全局函数/变量转为module.exports
    ["@babel/plugin-transform-modules-commonjs", { "allowTopLevelThis": true }]
  ]
}

步骤4:修改自定义测试环境(jest.env.js)

不再用VM执行,而是通过require加载转换后的模块,并挂载到全局:

const NodeEnvironment = require('jest-environment-node').TestEnvironment;
const path = require("path");

class CustomEnv extends NodeEnvironment {
  constructor(config, context) {
    super(config, context);
    this.loadContext();
  }

  loadContext() {
    // 加载经Babel转换后的模块
    const moduleExports = require(path.resolve('./src/index.js'));
    // 将模块导出的内容挂载到全局上下文
    Object.assign(this.global, moduleExports);
  }
}

module.exports = CustomEnv;

方法二:保留V8覆盖率,调整VM执行方式(需Jest支持)

如果不想切换到Babel,可以尝试让V8覆盖率工具识别VM中的脚本。修改jest.env.js,使用vm.Script并显式启用覆盖率追踪:

const NodeEnvironment = require('jest-environment-node').TestEnvironment;
const fs = require('fs');
const vm = require("vm");
const path = require("path");

class CustomEnv extends NodeEnvironment {
  constructor(config, context) {
    super(config, context);
    this.loadContext();
  }

  loadContext() {
    const filePath = path.resolve('./src/index.js');
    const js = fs.readFileSync(filePath, 'utf8');
    // 创建VM脚本时启用覆盖率选项
    const script = new vm.Script(js, {
      filename: filePath,
      displayErrors: true,
      coverage: true // 显式开启V8覆盖率追踪
    });
    const context = vm.createContext(this.global);
    script.runInContext(context);
    Object.assign(this.global, context);
  }
}

module.exports = CustomEnv;

注意:这种方法依赖V8的coverage选项支持,部分Node.js版本或Jest版本可能存在兼容性问题,若无效建议优先使用方法一。

执行npm t后,即可正常生成覆盖率报告。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 16:01:29