【问题标题】:How to test Nestjs interceptor?如何测试 Nestjs 拦截器?
【发布时间】: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?否则我应该如何进行?

【问题讨论】:

    标签: typescript unit-testing jestjs interceptor nestjs


    【解决方案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() 返回的对象的方法。
    猜你喜欢
    • 2021-11-22
    • 2022-10-14
    • 2021-07-15
    • 2021-02-11
    • 2020-12-12
    • 2020-04-24
    • 1970-01-01
    • 2021-05-04
    • 1970-01-01
    相关资源
    最近更新 更多