Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NestJS: How can I mock ExecutionContext in canActivate

I am having trouble in mocking ExecutionContext in Guard middleware.

Here's my RoleGuard extends JwtGuard

@Injectable()
export class RoleGuard extends JwtAuthGuard {
 ...
 async canActivate(context: ExecutionContext): Promise<boolean> {
    const request = context.switchToHttp().getRequest();
    const params = request.params;

    ...
 }
}

This is what I am trying on my unit test.

let context: ExecutionContext = jest.genMockFromModule('@nestjs/common');
  
context.switchToHttp = jest.fn().mockResolvedValue({
  getRequest: () => ({
   originalUrl: '/',
   method: 'GET',
   params: undefined,
   query: undefined,
   body: undefined,
  }),
  getResponse: () => ({
    statusCode: 200,
  }),
});
    
jest.spyOn(context.switchToHttp(), 'getRequest').mockImplementation(() => {
 return Promise.resolve(null);
});

And I am getting this kind of error.

Cannot spy the getRequest property because it is not a function; undefined given instead

I would like you to suggest any other way to mock context. Thank you.

like image 717
tmpacifitech Avatar asked Jun 26 '20 13:06

tmpacifitech


2 Answers

Please check this library https://www.npmjs.com/package/@golevelup/ts-jest

Then you could mock ExecutionContext as following.

import { createMock } from '@golevelup/ts-jest';
import { ExecutionContext } from '@nestjs/common';
 
describe('Mocked Execution Context', () => {
  it('should have a fully mocked Execution Context', () => {
    const mockExecutionContext = createMock<ExecutionContext>();
    expect(mockExecutionContext.switchToHttp()).toBeDefined();

    ...

  });
});

Hope it helps

like image 109
xyingsoft Avatar answered Nov 09 '22 00:11

xyingsoft


When it comes to the ExecutionContext, depending on what I'm tetsting, I just supply a simple object instead, something like

const ctxMock = {
  switchToHttp: () => ({
    getRequest: () => ({
      params: paramsToAdd,
      url: 'some url path',
      ...
    }),
  }),
}

And use that as I need. If I need access to jest functions I save those to a variable before hand and assign the context's function to the variable, then I can use expect(variable).toHaveBeenCalledTimes(x) without a problem.

Another option is to use @golevelup/ts-jest to create type safe mock objects for you. I've made extensive use of this library as well for other libraries I've made.

like image 32
Jay McDoniel Avatar answered Nov 09 '22 02:11

Jay McDoniel