CodePark/ questions / Testing NestJS apps
START PRACTICINGPRACTICE
Backend question · Backend testing › Testing NestJS apps

How do you test, in isolation, an interceptor that wraps every response as { data }, and the validation rules of a DTO used with ValidationPipe?

Call the class's main method directly. Interceptors and pipes are classes with one main method, so you don't need an HTTP app.

The interceptor. Pass it a stubbed ExecutionContext and a CallHandler. The CallHandler stands for the route handler. Its handle() returns an observable (an RxJS stream of values):
const out = interceptor.intercept(ctx, { handle: () => of({ id: 1 }) }).
Then read the result: expect(await lastValueFrom(out)).toEqual({ data: { id: 1 } }).
To test error mapping, return throwError(() => new Error('x')) from handle(). Then assert that the observable errors with the mapped exception.

The pipe. Create new ValidationPipe({ whitelist: true }). Call transform(value, { type: 'body', metatype: CreateUserDto }). The metatype tells the pipe which DTO class holds the rules. Assert two things:

  • Invalid input rejects with BadRequestException.
  • Valid input comes back as expected.

These tests are fast. An e2e (end-to-end) test still checks that the pipe and the interceptor are registered.

  • Call intercept() with a stub CallHandler that returns of(value).
  • Read the result with lastValueFrom, and test errors with throwError.
  • Call ValidationPipe.transform with metatype set to the DTO class.
  • Invalid input rejects with BadRequestException.