如何在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
相关产品推荐
相关产品推荐

