2 years ago

#75149

test-img

Ahmed J.

In a NestJs app, how to unitTest rolesGuard and test it with stub user and admin roles?

So I have this nestjs app that uses jwtAuthGuard and RolesGuard on some api calls. I want to write unit tests to test that a method call (say Delete) requires an admin Role and user role cant perform this operation. I want to unit test this with the RolesGuard.

Update: Below are the code samples, hope it clarify things. I provided some code about RolesGuard, authController and authController spec. I would like to, for example, test the rolesGuard for getUserById and check that the user has the correct role to access it or provide a forbidden message error.

RolesGuard

@Injectable()
export class RolesGuard implements CanActivate {
  private readonly logger = new Logger(RolesGuard.name)
  constructor(private reflector: Reflector, private authService: AuthService) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const requiredRoles = this.reflector.getAllAndOverride<Role[]>('roles', [context.getHandler(), context.getClass()])

    if (!requiredRoles) {
      return true
    }

    const { user } = context.switchToHttp().getRequest()

    if (!user) {
      this.logger.error('User was not found in request')
      return false
    }
    const currentUser = await this.authService.getCurrentUserById(user.userId)

    if (!currentUser) {
      this.logger.error(`User with id ${user.userId} not found`)
      return false
    }

    const hasRole = () => requiredRoles.some((requiredRole) => currentUser.role.includes(requiredRole))
    return user && user.role && hasRole()
  }
}

AuthController

...
 @Get('users/:userId')
  @UseGuards(JwtAuthGuard, RolesGuard)
  @Roles(Role.USER, Role.ADMIN)
  ...other dependencies
  async getUserById(@Req() request: Request, @Param('userId') userId: string): Promise<UserResponseDto> {
    this.logger.log('Get user by id')
    return await this.authService.getUserById(request, userId)
  }

AuthController.spec

...
describe('Auth Controller:', () => {
  let controller: AuthController
  let service: AuthService

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      imports: [],
      controllers: [AuthController],
      providers: [
        AuthService,
        {
          provide: JwtAuthGuard,
          useValue: jest.fn().mockImplementation(() => {
            return {
              canActivate: jest.fn().mockResolvedValue(() => {
                return true
              }),
            }
          }),
        },
        {
          provide: LocalAuthGuard,
          useValue: jest.fn().mockImplementation(() => {
            return { canActivate: jest.fn().mockResolvedValue(true) }
          }),
        },
        {
          provide: RefreshAuthGuard,
          useValue: jest.fn().mockImplementation(() => {
            return { canActivate: jest.fn().mockResolvedValue(true) }
          }),
        },
        {
          provide: RolesGuard,
          useValue: jest.fn().mockImplementation((req, res, next) => {
            return {
              canActivate: jest.fn().mockResolvedValue(() => {
                return {
                  roles: [Role.USER],
                }
              }),
            }
          }),
        },
      ],
    }).compile()

    controller = module.get<AuthController>(AuthController)
    service = module.get<AuthService>(AuthService)

    jest.clearAllMocks()
  })
...

Any help is appreciated.

authentication

jestjs

nestjs

user-roles

0 Answers

Your Answer

Accepted video resources