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

Jasmine编写Logger服务单元测试运行正常无代码覆盖率分数求助

问题根因

你当前的测试直接对Logger类自身的公开方法做了打桩(stub),实际运行测试时调用的是你伪造的stub方法,源码里的真实实现逻辑完全没有被执行,所以覆盖率工具无法统计到执行记录,自然不会返回有效覆盖率分数。

解决方案

我们需要Mock的是Logger内部依赖的Category实例,而非要测试的Logger本身,验证Logger的各个方法正确代理调用了内部Category实例的对应方法即可,同时覆盖error、fatal方法的两个分支(传Error/不传Error)拉满分支覆盖率。

调整后的单元测试代码(以Jest为例)

import { Logger } from "./logging.service";
import { Category } from 'typescript-logging';

// 全局mock Category类
jest.mock('typescript-logging', () => {
  const mockCategoryInstance = {
    trace: jest.fn(),
    debug: jest.fn(),
    info: jest.fn(),
    warn: jest.fn(),
    error: jest.fn(),
    fatal: jest.fn()
  };
  return {
    Category: jest.fn(() => mockCategoryInstance)
  };
});

describe("Logger", () => {
  let logger: Logger;
  let mockCategoryInstance: jest.Mocked<Category>;

  beforeEach(() => {
    // 重置所有mock调用记录
    jest.clearAllMocks();
    logger = new Logger();
    // 获取内部初始化的mock Category实例
    mockCategoryInstance = (Category as jest.Mock).mock.results[0].value;
  });

  it("调用trace方法时正确代理到内部Category实例的trace方法", () => {
    const testMsg = '测试trace信息';
    logger.trace(testMsg);
    expect(mockCategoryInstance.trace).toHaveBeenCalledWith(testMsg);
  });

  it("调用debug方法时正确代理到内部Category实例的debug方法", () => {
    const testMsg = '测试debug信息';
    logger.debug(testMsg);
    expect(mockCategoryInstance.debug).toHaveBeenCalledWith(testMsg);
  });

  it("调用info方法时正确代理到内部Category实例的info方法", () => {
    const testMsg = '测试info信息';
    logger.info(testMsg);
    expect(mockCategoryInstance.info).toHaveBeenCalledWith(testMsg);
  });

  it("调用warn方法时正确代理到内部Category实例的warn方法", () => {
    const testMsg = '测试warn信息';
    logger.warn(testMsg);
    expect(mockCategoryInstance.warn).toHaveBeenCalledWith(testMsg);
  });

  it("调用error方法且不传Error参数时,正确代理调用", () => {
    const testMsg = '测试error信息';
    logger.error(testMsg);
    expect(mockCategoryInstance.error).toHaveBeenCalledWith(testMsg, null);
  });

  it("调用error方法且传入Error参数时,正确代理调用", () => {
    const testMsg = '测试error信息';
    const testError = new Error('测试错误');
    logger.error(testMsg, testError);
    expect(mockCategoryInstance.error).toHaveBeenCalledWith(testMsg, testError);
  });

  it("调用fatal方法且不传Error参数时,正确代理调用", () => {
    const testMsg = '测试fatal信息';
    logger.fatal(testMsg);
    expect(mockCategoryInstance.fatal).toHaveBeenCalledWith(testMsg, null);
  });

  it("调用fatal方法且传入Error参数时,正确代理调用", () => {
    const testMsg = '测试fatal信息';
    const testError = new Error('测试致命错误');
    logger.fatal(testMsg, testError);
    expect(mockCategoryInstance.fatal).toHaveBeenCalledWith(testMsg, testError);
  });
});

如果使用Vitest作为测试框架,将上述代码中的jest替换为vi即可,逻辑完全一致。

额外检查项

如果调整测试后仍然没有覆盖率输出,检查你的覆盖率工具配置:

  • Jest场景:检查jest.config.js中的collectCoverageFrom配置是否包含了你的logging.service.ts文件路径,排除了测试文件、声明文件等不需要统计的内容
  • 确保运行测试时开启了覆盖率参数,比如Jest需要加--coverage参数运行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 10:15:06