skip to Main Content

I would like to create a unit test for a very simple custom decorator, but I can’t.
My decorator was born following the solution given here.
I have authentication via Keycloak and with this solution in my controllers I can get the user object corresponding to the token.

I then use the decorator like this:

import {
  Body,
  Controller,
  Post,
  UseGuards,
  UsePipes,
  ValidationPipe,
} from '@nestjs/common'
import { LogbooksService } from './logbooks.service'
import { User } from 'src/typeorm/user.entity'
import { AuthUser } from 'src/users/users.decorator'
import { UsersGuard } from 'src/users/users.guard'
import { CreateLogbookDto } from './dto/CreateLogbook.dto'

@Controller('logbooks')
export class LogbooksController {
  constructor(private readonly logbookService: LogbooksService) {}

  @Post()
  @UseGuards(UsersGuard)
  @UsePipes(ValidationPipe)
  async createLogbook(
    @Body() createLogbookDto: CreateLogbookDto,
    @AuthUser('user') user: User,
  ) {
    const newLogbook = await this.logbookService.createLogbook(
      createLogbookDto,
      user,
    )
    return newLogbook
  }
}

And this is the simple decorator

import { createParamDecorator } from '@nestjs/common'

export const AuthUser = createParamDecorator((data: string, req) => {
  return req.args[0].principal
})

The nest version is 10.2.1

How can I do this?
Thanks

2

Answers


  1. Chosen as BEST ANSWER

    I found a solution:

    function getParamDecoratorFactory(decorator: unknown) {
        class TestDecorator {
          public test(@AuthUser() value) {
            console.log(value)
            console.log(decorator)
          }
        }
    
        const args = Reflect.getMetadata(ROUTE_ARGS_METADATA, TestDecorator, 'test')
        return args[Object.keys(args)[0]].factory
      }
    ...Creating Test Module
    
    describe('decorator', () => {
        it('Decorator Test', () => {
          const req = httpMock.createRequest()
          const res = httpMock.createResponse()
          req.user = { principal: {} }
          const ctx = new ExecutionContextHost(
            [req, res],
            LogbooksController,
            logbookController.createLogbook,
          )
          const factory = getParamDecoratorFactory(AuthUser)
          user = factory('user', ctx)
        })
      })
    

    1. that decorator is outdated and will not work in Nest v10. The req being the second parameter for Nest v7 if I recall correctly. The new custom decorator should be:
    export const AuthUser = createParamDecorator((data: string, ctx: ExecutionContext) => {
      const req = ctx.switchToHttp().getRequest()
      return req[data].principle
    })
    

    As that will get req.user.principle like you’re trying to.

    1. There’s not an easy way to make a unit test for something like this, other than extracting out the callback passed to createParamDecorator, which is an option, but this is better tested via integration or e2e tests that actually send requests to the server
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search