如何测试 Nestjs 拦截器?

Posted

技术标签:

【中文标题】如何测试 Nestjs 拦截器?【英文标题】:How to test Nestjs interceptor? 【发布时间】:2020-01-03 21:47:00 【问题描述】:

我找不到任何关于如何在 NestJS 中测试拦截器的解释

这个简单的例子截取了一个 POST 查询以向正文中提供的示例模型添加一个属性。

@Injectable()
export class SubscriberInterceptor implements NestInterceptor 
  async intercept(
    context: ExecutionContext,
    next: CallHandler,
  ): Promise<Observable<ExampleModel>> 
    let body: ExampleModel = context.switchToHttp().getRequest().body;
    body = 
      ...body,
      addedAttribute: 'example',
    ;
    context.switchToHttp().getRequest().body = body;
    return next.handle();
  

我想测试拦截函数中发生了什么。

到目前为止:

const interceptor = new SubscriberInterceptor();

describe('SubscriberInterceptor', () => 
  it('should be defined', () => 
    expect(interceptor).toBeDefined();
  );

  describe('#intercept', () => 
    it('should add the addedAttribute to the body', async () => 
      expect(await interceptor.intercept(arg1, arg2)).toBe( ...bodyMock, addedAttribute: 'example' );
    );
  );
);

我的问题:我应该只模拟 arg1: ExecutionContextarg2: CallHandler 吗?如果是这样,如何模拟arg1arg2?否则我应该如何进行?

【问题讨论】:

【参考方案1】:

你是对的,你应该模拟arg1arg2,然后将它们传递给intercept方法,这里是解决方案:

SubscriberInterceptor.ts:

interface ExecutionContext 
  switchToHttp(): any;

interface CallHandler 
  handle(): any;

interface Observable<T> 
interface ExampleModel 

interface NestInterceptor 
  intercept(context: ExecutionContext, next: CallHandler): Promise<Observable<ExampleModel>>;


export class SubscriberInterceptor implements NestInterceptor 
  public async intercept(context: ExecutionContext, next: CallHandler): Promise<Observable<ExampleModel>> 
    let body: ExampleModel = context.switchToHttp().getRequest().body;
    body = 
      ...body,
      addedAttribute: 'example'
    ;
    context.switchToHttp().getRequest().body = body;
    return next.handle();
  


单元测试,executionContext的模拟链式方法

import  SubscriberInterceptor  from './';

const interceptor = new SubscriberInterceptor();

const executionContext = 
  switchToHttp: jest.fn().mockReturnThis(),
  getRequest: jest.fn().mockReturnThis()
;

const callHandler = 
  handle: jest.fn()
;

describe('SubscriberInterceptor', () => 
  it('should be defined', () => 
    expect(interceptor).toBeDefined();
  );
  describe('#intercept', () => 
    it('t1', async () => 
      (executionContext.switchToHttp().getRequest as jest.Mock<any, any>).mockReturnValueOnce(
        body:  data: 'mocked data' 
      );
      callHandler.handle.mockResolvedValueOnce('next handle');
      const actualValue = await interceptor.intercept(executionContext, callHandler);
      expect(actualValue).toBe('next handle');
      expect(executionContext.switchToHttp().getRequest().body).toEqual(
        data: 'mocked data',
        addedAttribute: 'example'
      );
      expect(callHandler.handle).toBeCalledTimes(1);
    );
  );
);

单元测试结果:

 PASS  src/mock-function/57730120/index.spec.ts
  SubscriberInterceptor
    ✓ should be defined (10ms)
    #intercept
      ✓ t1 (11ms)

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        1.235s, estimated 3s

【讨论】:

当 getRequest 不是 ExecutionContext 的方法时,它是如何工作的?它是从 switchtoHttp() 返回的对象的方法。

以上是关于如何测试 Nestjs 拦截器?的主要内容,如果未能解决你的问题,请参考以下文章

如何在nestjs拦截器中检测控制器?

如何在 NestJS 拦截器中获取处理程序路由(对于 Express 和 Fastify)

如何在 neo4j-graphql-js 端点中使用带有 nestjs 框架的拦截器?

如何在发送 Nestjs 之前格式化响应?

NestJS:拦截地图和catchError

nestjs 文件上传