jvhang
jvhang

Reputation: 777

ClassSerializeInterceptor in Nest.JS Unit Tests

Is it possible to use ClassSerializeInterceptor while testing Nest.JS controllers?

Our issue is that the ClassSerializeInterceptor works fine as part of the app but does not run when the controller is instantiated as part of a unit test. I tried providing ClassSerializeInterdeptor as part of the Testing Module but no luck.

Example code:

Test

describe('AppController', () => {
  let appController: AppController;

  beforeEach(async () => {
    const app: TestingModule = await Test.createTestingModule({
      controllers: [AppController],
      providers: [AppService,  ClassSerializerInterceptor],
    }).compile();

    appController = app.get<AppController>(AppController);
  });

  describe('root',  () => {
    it('should not expose exlcuded fields"', async  () => {

      // expect(appController.getHello()).toBe('Hello World!');

      const s = await appController.getHello();

      expect(s).toHaveProperty('shouldBeIncluded');
      expect(s).not.toHaveProperty('shouldBeRemoved');

    });
  });
});

Test Entity:

@ObjectType()
@Entity()
export class TestEntity {

  @Field(type => ID)
  @PrimaryGeneratedColumn('uuid')
  shouldBeIncluded: string;

  @Column({ nullable: true })
  @Exclude()
  shouldBeRemoved: string;
}

Upvotes: 1

Views: 715

Answers (2)

Chu Phong
Chu Phong

Reputation: 71

You can use:

import { createMock } from '@golevelup/ts-jest';
import { Test } from '@nestjs/testing';
import { Reflector } from '@nestjs/core';
import {
  CallHandler,
  ClassSerializerInterceptor,
  ExecutionContext,
} from '@nestjs/common';

const executionContext = createMock<ExecutionContext>();
const callHandler = createMock<CallHandler>();

const app = await Test.createTestingModule({}).compile();
const reflector = app.get(Reflector);
const serializer = new ClassSerializerInterceptor(reflector, {
  strategy: 'excludeAll',
});

callHandler.handle.mockReturnValueOnce(from(['Hello world']));

const actualResult = await lastValueFrom(serializer.intercept(executionContext, callHandler));

expect(actualResult).toEqual('Hello world')

Upvotes: 0

Jay McDoniel
Jay McDoniel

Reputation: 70490

Testing interceptors as a part of the request flow can only be done in e2e and partial integration test. You'll need to set up a supertest instance as described in the docs and send in the request to ensure that the ClassSerializeInterceptor is running as you expect it to.

Upvotes: 1

Related Questions