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

如何用Jest测试NestJS中@Query()装饰器以实现100%覆盖率?

解决NestJS Resolver中@Query装饰器的测试覆盖率问题

要覆盖@Query()装饰器所在行的测试覆盖率,核心是让Nest的元数据系统真正执行装饰器内的逻辑,而非仅单独实例化Resolver类。以下是具体实现步骤:

1. 使用Nest测试模块完整加载Resolver

通过Test.createTestingModule初始化包含GraphQL模块的测试容器,让Nest自动解析并执行Resolver上的装饰器逻辑,这是最可靠的方式:

import { Test } from '@nestjs/testing';
import { MyResolver } from './my.resolver';
import { GraphQLModule } from '@nestjs/graphql';
import { Person } from './person.entity'; // 引入你的实体类

describe('MyResolver', () => {
  let resolver: MyResolver;

  beforeEach(async () => {
    const moduleRef = await Test.createTestingModule({
      imports: [
        GraphQLModule.forRoot({
          autoSchemaFile: true, // 自动生成Schema触发装饰器解析
        }),
      ],
      providers: [MyResolver],
    }).compile();

    resolver = moduleRef.get<MyResolver>(MyResolver);
  });

  // 基础测试:确保Resolver被正确初始化(触发装饰器执行)
  it('should be defined', () => {
    expect(resolver).toBeDefined();
  });

  // 业务逻辑测试:覆盖getPerson方法的同时,确保装饰器逻辑被统计
  it('should return logged-in person', async () => {
    // 模拟装饰器注入的参数
    const mockToken = 'valid-token-123';
    const mockContext = {};
    const mockProfiles = ['user', 'admin'];

    const result = await resolver.getPerson(mockToken, mockContext, mockProfiles);
    expect(result).toBeInstanceOf(Person);
    // 可根据业务逻辑添加更多断言
  });
});

2. 排查覆盖率配置问题

如果按上述方法仍未覆盖装饰器行,检查你的jest.config.js配置,确保没有排除Resolver文件:

module.exports = {
  // 其他配置...
  collectCoverageFrom: [
    'src/**/*.ts',
    '!src/**/*.module.ts', // 排除模块文件(可选)
    '!src/main.ts', // 排除入口文件(可选)
  ],
  coveragePathIgnorePatterns: [
    // 不要将你的Resolver文件加入忽略列表
  ],
};

关键原理说明

@Query()和@Resolver()装饰器本质是在类/方法定义时向Nest注册元数据,但Jest默认不会将模块加载阶段的装饰器执行逻辑纳入测试覆盖率,除非通过测试模块编译触发完整的元数据解析流程。单独实例化new MyResolver()只会执行类构造逻辑,不会触发装饰器内的Nest元数据注册逻辑,因此无法覆盖装饰器行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 23:18:34