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

为何Vitest/Jest中被Mock的JS导入仍有非零代码覆盖率?

问题原因与解决方案

问题根源

你遇到的情况是Vitest自动Mock机制的特性导致的:当你调用vi.mock('./service')但未提供自定义Mock工厂函数时,Vitest会自动生成一个与原始模块结构匹配的Mock。为了匹配结构,它会加载原始的service.js模块来解析导出内容(比如确认这是一个类),这个加载过程会执行原始模块的类定义代码(类声明、类的大括号部分),因此这部分代码被统计进了覆盖率;而类的serviceFn方法因为被你用vi.spyOn替换了实现,没有执行原始代码,所以显示未覆盖。

你的Mock本身是生效的(测试能通过证明这一点),只是覆盖率统计到了Vitest自动Mock时加载原始模块的额外代码。


解决方案

方案1:手动编写完全Mock,避免加载原始模块

修改测试文件中的vi.mock逻辑,手动提供Mock工厂函数,完全替换原始模块的实现,这样Vitest就不会加载原始的service.js:

import { describe, expect, it, vi } from 'vitest';
import { indexFn } from './index';
import Service from './service';

// 手动Mock整个Service类,完全替代原始实现
vi.mock('./service', () => ({
  default: vi.fn().mockImplementation(() => ({
    serviceFn: vi.fn()
  }))
}));

describe('suite', () => {
  it('tests', () => {
    const mockedReturn = 'mockedReturn';
    vi.spyOn(Service.prototype, 'serviceFn').mockReturnValue(mockedReturn);
    expect(indexFn()).toBe(mockedReturn);
  });
});

修改后,原始service.js不会被加载,覆盖率报告中就不会出现它的统计数据。

方案2:在覆盖率配置中排除目标文件

如果你不想修改测试代码,可以在Vitest配置文件(如vitest.config.js)中设置覆盖率排除规则,忽略service.js:

import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    coverage: {
      exclude: [
        'service.js' // 排除该文件的覆盖率统计
      ]
    }
  }
});

也可以更精确地指定只统计需要测试的文件:

coverage: {
  include: [
    'index.js'
  ]
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 05:35:29