如何用Jest测试Nestjs中的超时拦截器

kmb7vmvb  于 2022-12-16  发布在  Jest
关注(0)|答案(2)|浏览(179)

我找不到任何关于如何在NestJS中测试拦截器的说明。
请帮我用笑话测试一下拦截器?

import { Injectable, NestInterceptor, ExecutionContext, CallHandler, RequestTimeoutException } from "@nestjs/common";
import { Observable, throwError, TimeoutError } from "rxjs";
import { catchError, timeout } from "rxjs/operators";

@Injectable()
export class TimeoutInterceptor implements NestInterceptor {
    constructor(private readonly interval: number) {}

    intercept(_context: ExecutionContext, next: CallHandler): Observable<any> {
        if (this.interval > 0) {
            return next.handle().pipe(
                timeout(this.interval),
                catchError((error) => {
                    if (error instanceof TimeoutError) {
                        return throwError(new RequestTimeoutException(`The operation timed out. `));
                    }
                    return throwError(error);
                }),
            );
        }
        return next.handle();
    }
}
4ioopgfo

4ioopgfo1#

我曾经试着为这个拦截器编写单元测试,但我不喜欢它:/看:https://gist.github.com/micalevisk/33d793202541f044d8f5bccb81049b94

nx7onnlm

nx7onnlm2#

我试着在那里找到类似的问题,希望有人愿意回答,但直到今天我仍然一无所获。尽管如此,我还是试着独自解决这个问题。对于那些可能正在寻找解决方案的人来说。
让我们看一看nestjsdocs中的简单超时拦截器示例

import { Injectable, NestInterceptor, ExecutionContext, CallHandler, RequestTimeoutException } from '@nestjs/common';
import { Observable, throwError, TimeoutError } from 'rxjs';
import { catchError, timeout } from 'rxjs/operators';

@Injectable()
export class TimeoutInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handle().pipe(
      timeout(5000),
      catchError(err => {
        if (err instanceof TimeoutError) {
          return throwError(() => new RequestTimeoutException());
        }
        return throwError(() => err);
      }),
    );
  };
};

测试可观察对象内部错误的可能单元测试是模拟指定时间(延迟)后的返回值。在这种情况下,它将大于5000。这可以通过使用delay rxjs运算符来实现。
因此,这个超时拦截器的适当单元测试应该类似于以下内容。

describe('TimeoutInterceptor', () => {
  const executionContext = mockedExecutionContext; // your mocked execution context
  const callHandler = mockedCallHandler; // your mocked call handler

  let timeoutInterceptor: TimeoutInterceptor;

  beforeEach(async () => {
    const moduleRef = await Test.createTestingModule({
      providers: [TimeoutInterceptor],
    }).compile();

    timeoutInterceptor = moduleRef.get<TimeoutInterceptor>(TimeoutInterceptor);
  });

  describe('when intercept is called', () => {
    const returnedValue: [] = [];

    describe('and the request time is not exceeded the max allowed timeout in ms', () => {
      it(`should return the to be returned value`, (done: any) => {
        callHandler.handle.mockReturnValue(
          of(returnedValue).pipe(
            delay(2500), // below 5000
          ),
        );

        timeoutInterceptor.intercept(executionContext, callHandler).subscribe({
          next(value) {
            expect(value).toStrictEqual(returnedValue);
          },
          complete() {
            done();
          },
        });
      });
    });

    describe('and the request time exceeded (+1000ms) the max allowed timeout in ms', () => {
      it(`should throw ${RequestTimeoutException.name}`, (done: any) => {
        callHandler.handle.mockReturnValue(
          of(returnedValue).pipe(delay(5000 + 1000)), // 5000 + 1000ms
        );

        timeoutInterceptor.intercept(executionContext, callHandler).subscribe({
          error(err) {
            expect(err).toBeInstanceOf(RequestTimeoutException);
            done(); // don't forget to invoke this done, or the test will be hang
          },
        });
      });
    });
  });
});

相关问题