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

如何在NestJS端到端测试中Mock自定义Firewall装饰器并验证参数

如何在NestJS E2E测试中Mock自定义装饰器并验证调用参数

要Mock自定义的Firewall装饰器并验证其调用参数,核心思路是利用Jest的模块Mock能力,在控制器导入前替换装饰器为可跟踪的Spy函数。以下是具体实现步骤:

1. 提前Mock装饰器模块

由于装饰器在类导入阶段就会执行,必须在测试文件顶部先Mock装饰器所在的模块,确保控制器使用的是Mock后的装饰器。

假设你的Firewall装饰器位于src/decorators/firewall.decorator.ts,在测试文件顶部添加Mock逻辑:

import * as request from 'supertest';
import { Test } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import { AppModule } from 'src/app.module';
// 导入装饰器所在模块
import * as FirewallModule from 'src/decorators/firewall.decorator';

// Mock模块,替换Firewall为Spy函数
jest.mock('src/decorators/firewall.decorator', () => ({
  // 保留模块其他原有导出(如果有)
  ...jest.requireActual('src/decorators/firewall.decorator'),
  // 将Firewall替换为jest Mock函数,返回空装饰器不影响接口逻辑
  Firewall: jest.fn(() => (target: any, key: string, desc: PropertyDescriptor) => desc),
}));

2. 跟踪装饰器调用并验证参数

在测试用例中,通过Mock的Spy函数跟踪Firewall的调用情况,验证传入的参数是否符合预期:

describe('Some Controller', () => {
  let app: INestApplication;
  // 类型断言将Firewall转为jest.Mock,方便调用Spy方法
  const firewallSpy = FirewallModule.Firewall as jest.Mock;

  beforeAll(async () => {
    const moduleRef = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = moduleRef.createNestApplication();
    await app.init();
  });

  // 每个测试前清空Spy的调用记录,避免干扰
  beforeEach(() => {
    firewallSpy.mockClear();
  });

  it('Firewall装饰器应被正确调用(无参数)', async () => {
    // 请求接口触发装饰器逻辑
    await request(app.getHttpServer()).get('/some/testEndpoint').expect(200);
    
    // 验证装饰器被调用,且传入参数为undefined(对应@Firewall())
    expect(firewallSpy).toHaveBeenCalledWith(undefined);
  });

  // 扩展测试:验证带参数的装饰器调用
  it('Firewall装饰器应被正确调用(带skipThrottle参数)', async () => {
    // 假设有另一个接口使用@Firewall({ skipThrottle: true })
    await request(app.getHttpServer()).get('/some/unthrottled-endpoint').expect(200);
    
    expect(firewallSpy).toHaveBeenCalledWith({ skipThrottle: true });
  });

  afterAll(async () => {
    await app.close();
  });
});

关键说明

  • Mock时机:必须在导入控制器/模块前完成Mock,否则原装饰器会先执行,导致Spy无法跟踪。
  • 空装饰器返回值:Mock的Firewall返回一个空装饰器(直接返回属性描述符),这样不会影响接口原有业务逻辑的执行。
  • Spy复用:通过beforeEach清空Spy调用记录,确保每个测试用例的独立性。

如果需要验证装饰器内部的逻辑(比如是否正确应用了Throttle或SkipThrottle),可以调整Mock的返回值,或者直接测试接口的限流行为(比如快速多次请求看是否触发429)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 16:36:42