Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NestJS mock JWT authentication in e2e tests

I want to mock JWT Authentication in my NestJS e2e (integration) tests. I use injected token data in my business logic, and I don't want to insert credentials on my test code.

I implemented JWT authentication as per the Nest authentication docs. I use a decorator (similar) to the @User decorator in the examples, and use information on the User object in my business logic.

@Post()
async myPostEndpoint(@Body() body: PostBody, @User() user: MyUser){
    // do stuff using user properties
}

When testing my application using supertest as indicated in the Nest testing docs, I don't want to make a real authentication request, as I would need to persist credentials in my version control system.

I expected to be able to override providers to return a test user. But couldn't figure it out.

I tried overriding the AuthService's validateClient and login to return a default user using overrideProvider + useClass/useFactory/useValue as indicated in the Nest testing docs. I also tried overriding methods in JwtStrategy and LocalStrategy, but the requests still return 401 - Unauthorized.

like image 297
Cassiano Avatar asked Aug 23 '19 15:08

Cassiano


2 Answers

In your overrideGuard(AuthGuard('jwt')).useValue() you can add functionality to your canActivate() function to look like the following:

canActivate (context: ExecutionContext) => {
  const req = context.switchToHttp().getRequest();
  req.user = myCustomUserObject;
  return true;
}

Where myCustomUserObject is the expected value of req.user for the server to handle.

like image 52
Jay McDoniel Avatar answered Nov 20 '22 11:11

Jay McDoniel


For people using GraphQL, this is what I did:

const module: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    })
      .overrideGuard(JwtAuthGuard)
      .useValue({
        canActivate: (context: ExecutionContext) => {
          const ctx = GqlExecutionContext.create(context)
          ctx.getContext().req.user = { user_id: "abc123" } // Your user object
          return true
        },
      })
      .compile()
like image 13
BryceLarkin Avatar answered Nov 20 '22 12:11

BryceLarkin