How can I mock 'nest-keycloak-connect' guard in nestJs controller unit-test?

559 Views Asked by At

I have a simple controller that uses nest-keycloak-connect implementation of guard to restrict access to the resource. This is a snippet of the controller's code:

import { AuthGuard, ResourceGuard, Roles } from 'nest-keycloak-connect';

@UseGuards(AuthGuard, ResourceGuard)
@Controller('v1/info')
export class InfoController {
  constructor(private readonly infoService: InfoService) {}

  @Post('/storeinfo')
  @Roles({ roles: ['USER'] })
  @HttpCode(HttpStatus.OK)
  async storeInfo(@Body() payload: InfoRequest): Promise<any> {

...
    return response;
  }
}

It works fine, but now I have to compose a unit-test for it. I got to a problem while trying to create the test module for it. I began with the

import { AuthGuard } from 'nest-keycloak-connect';

...
  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      controllers: [InfoController],
      providers: [
        InfoService,
        {
          provide: AuthGuard,
          useValue: jest.fn().mockImplementation(() => true),
        },
      ],
    })
      .overrideProvider(InfoService)
      .useClass(InfoService)
      .compile();

    controller = module.get<InfoController>(InfoController);
    claimsService = module.get<InfoService>(InfoService);
  });

It failed with the error: Nest can't resolve dependencies of the AuthGuard (?, KEYCLOAK_CONNECT_OPTIONS, KEYCLOAK_LOGGER, KeycloakMultiTenantService, Reflector). Please make sure that the argument KEYCLOAK_INSTANCE at index [0] is available in the RootTestModule context

I tried to add all required providers one by one for these dependencies up to this point:

import {
  AuthGuard,
  KEYCLOAK_INSTANCE,
  KEYCLOAK_CONNECT_OPTIONS,
  KEYCLOAK_LOGGER,
  KeycloakMultiTenantService,
} from 'nest-keycloak-connect';
...
  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      controllers: [InfoController],
      providers: [
        InfoService,
        {
          provide: AuthGuard,
          useValue: jest.fn().mockImplementation(() => true),
        },
        {
          provide: KEYCLOAK_INSTANCE,
          useValue: jest.fn().mockImplementation(() => true),
        },
        {
          provide: KEYCLOAK_CONNECT_OPTIONS,
          useValue: jest.fn().mockImplementation(() => true),
        },
        {
          provide: KEYCLOAK_LOGGER,
          useValue: jest.fn().mockImplementation(() => true),
        },
        {
          provide: KeycloakMultiTenantService,
          useValue: jest.fn().mockImplementation(() => true),
        },
      ],
    })
      .overrideProvider(InfoService)
      .useClass(InfoService)
      .compile();

    controller = module.get<InfoController>(InfoController);
    claimsService = module.get<InfoService>(InfoService);
  });

when it failed with the error

Nest can't resolve dependencies of the AuthGuard (KEYCLOAK_INSTANCE, KEYCLOAK_CONNECT_OPTIONS, KEYCLOAK_LOGGER, ?, Reflector). Please make sure that the argument KeycloakMultiTenantService at index [3] is available in the RootTestModule context

but 'nest-keycloak-connect' does not export the KeycloakMultiTenantService class:

error TS2724: '"nest-keycloak-connect"' has no exported member named 'KeycloakMultiTenantService'

so I'm totally stuck. I'm a newbie in typescript but I understand that I made a mess in the code above and it's quite possible I'm trying to do it in a wrong way. So question is: is it possible to mock nest-keycloak-connect's implementation of guard and test a nestJS guarded controller?

0

There are 0 best solutions below