Skip to content

Testing Guards

Robert Main edited this page Dec 12, 2019 · 2 revisions

Authentication in this application is currently being performed by passport which provides authentication middleware to protect certain API routes from access by unauthenticated users.

Generally, it is not desireable for tests to be interacting with authentication sources. Therefore, the canActivate method in passport is typically stubbed out to prevent this, like so:

beforeEach(function () {
  stub(AuthGuard('saml').prototype, 'canActivate');
});
afterEach(function () {
  AuthGuard('saml').prototype.canActivate.restore();
});

Additionally, implementations of the CanActivate interface must have a canActivate method, which, in turn recieves an ExecutionContext as it's only parameter.

ExecutionContext contains metadata about the handler the guard is bound to, the current HTTP request and other parts of the application that may be used to determine whether a guard should allow or deny access. In certain cases(for example, when only performing authentication), the specifics of ExecutionContext may be irrelevant, and a simple object literal can be provided to canActivate in testing.

strictEqual(myGuard.canActivate({} as ExecutionContext), true);

For other guards that may need to examine parts of the HTTP request (for example for access control etc.) a stub ExecutionContext may be used in testing. This can be done like so:

const context: Partial<ExecutionContext> = {
  switchToHttp: stub().returns({
    getRequest: stub(),
    getResponse: stub(),
    getNext: stub(),
  } as HttpArgumetsHost),
};

strictEqual(myGuard.canActivate(context as ExecutionContext), true);

From there, the switchToHttp().getRequest() can be used within the guard to obtain access to parts of the application(such as the current HTTP request) like so:

const request = context.switchToHttp().getRequest();
const user = request.user;

See https://docs.nestjs.com/guards#putting-it-all-together for more info

Clone this wiki locally