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

NestJS项目中members.service.ts无法实现完整测试覆盖率如何解决

问题根因

你当前的测试逻辑存在核心错误:直接将整个MembersService替换为自定义的Mock类,所有测试用例执行的都是Mock类的方法,完全没有运行真实members.service.ts中的业务代码,这就是覆盖率极低的根本原因。
我们的测试思路应该是:保留真实的MembersService实例,只Mock它依赖的外部资源(这里就是mongoose注入的financeMembersModel模型)。

修正后的测试代码

import { Test, TestingModule } from '@nestjs/testing';
import { MembersService } from './members.service';
import { memberData } from './mockMembersData';
import { HttpException } from '@nestjs/common';

// 只Mock mongoose返回的链式查询方法
const mockFind = jest.fn().mockReturnThis();
const mockSort = jest.fn().mockReturnThis();
const mockLimit = jest.fn();

describe('MembersService', () => {
  let membersService: MembersService;

  beforeAll(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        MembersService,
        {
          // 替换注入的mongoose模型为Mock对象
          provide: 'finance_members',
          useValue: {
            find: mockFind,
            sort: mockSort,
            limit: mockLimit
          }
        }
      ],
    }).compile();
    membersService = module.get<MembersService>(MembersService);
  });

  // 每个用例执行前清空之前的mock调用记录
  beforeEach(() => {
    jest.clearAllMocks();
  })

  it('service 实例正常初始化', () => {
    expect(membersService).toBeDefined();
  });

  it('查询会员详情成功,返回对应数据', async () => {
    // 模拟limit返回正常的会员数组
    mockLimit.mockResolvedValue([memberData]);
    const result = await membersService.getMemberDetails('test_guid_123');
    // 验证调用链路参数是否正确
    expect(mockFind).toHaveBeenCalledWith({ guid: 'test_guid_123' });
    expect(mockSort).toHaveBeenCalledWith({ _id: -1 });
    expect(mockLimit).toHaveBeenCalledWith(1);
    expect(result).toEqual(memberData);
  });

  it('查询不到对应会员,返回undefined', async () => {
    // 模拟limit返回空数组
    mockLimit.mockResolvedValue([]);
    const result = await membersService.getMemberDetails('not_exist_guid');
    expect(result).toBeUndefined();
  });

  it('查询出现异常,抛出对应HttpException', async () => {
    // 模拟查询抛出错误
    const mockError = {
      response: { status: 400 },
      message: '数据库查询错误'
    };
    mockLimit.mockRejectedValue(mockError);
    await expect(membersService.getMemberDetails('error_guid')).rejects.toThrow(HttpException);
    await expect(membersService.getMemberDetails('error_guid')).rejects.toMatchObject({
      status: 400,
      response: { ...mockError }
    });
  });
});

覆盖率提升说明

上述测试用例覆盖了getMemberDetails方法的所有分支:

  • try块的正常查询、返回空值场景
  • catch块的异常抛出场景
    运行测试后你的service文件覆盖率可以达到100%,完全满足80%的要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.18 04:06:04