3

I am new to nestjs and to jest as well. I am trying to override a guard, but it's not working. So my folder structure is: "src/app.module.ts", "src/modules/auth/guards/myfile-guard.ts", "src/modules/auth/auth.module.ts","src/modules/user/user.controller.ts" and "src/modules/user" contains all user related files. I am testing e2e test for user controller, which have a get route "/users", which requires user to login, and it is determined by a guard and then mentioned of this guard is done in "src/modules/auth/auth.module.ts" as below:

@Module({
  imports: [],
  controllers: [AuthController],
  providers: [
    {
      provide: APP_GUARD,
      useClass: IsAuthenticatedGuard,
    },
    AuthService,
  ],
  exports: [AuthService],
})
export class AuthModule {}

my guard file: "src/modules/auth/guards/myfile-guard.ts" looks like:

@Injectable()
export class MyGuard extends AuthGuard('local')
  implements CanActivate {
  constructor(private readonly reflector: Reflector) {
    super();
  }
  public canActivate(context: ExecutionContext): boolean {
    const isPublic = this.reflector.get<boolean>(
      'isPublic',
      context.getHandler(),
    );
    if (isPublic) {
      return true;
    }
    const request = context.switchToHttp().getRequest<Request>();
    const isAuthenticated = request.isAuthenticated();
    if (!isAuthenticated) {
      throw new UnauthorizedException();
    }
    return true;
  }
}

"src/app.module.ts" file, I have below code:

@Module({
  imports: [
    AuthModule,
    UserModule,
  ],
  controllers: [AppController],
  providers: [],
})
export class AppModule {}

in "src/modules/user/user.controller.ts" file, I have below code:

@Controller('users')
export class UserController {
  constructor(private readonly userService: UserService) {}
  @Get()
  async getUsers(): Promise<User[]> {
    return this.userService.findUsers();
  }
}

in "src/test/user-e2e-spec.ts" file, I have below code:

import { MyGuard } from '../src/modules/auth/guards/myfile-guard';
import { AppModule } from '../src/app.module';
describe('UserController (e2e)', () => {
  let app: INestApplication;
  const canActivate = jest.fn(() => true);
  beforeEach(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
      providers: [],
    })
      .overrideGuard(MyGuard)
      .useValue({ canActivate })
      .compile();
    app = moduleFixture.createNestApplication();
    jest.resetAllMocks();
    await app.init();
  });
  describe('@Get()', () => {
    const requestUrl = '/users';
    canActivate.mockReturnValueOnce(true);
    it('returns list of users', async () => {
      return request(app.getHttpServer())
        .get(requestUrl)
        .expect(200);
    });
  });
});

When I run the test, in place of 200, I always get 401 unauthorized, which means, "MyGuard" is not getting overridden by {canActivate}, I did even console.log in MyGuard class, it always goes there, where as it should not, I tried to search different questions related to same, few of them helped me to reach at this stage as well, below are few links which I already visited and which helped me: Nestjs unit-test - mock method guard Controller integration testing with nestJS using different guards

but still I cannot get it working as per the need, which is returning true from mocked or overridden canActivate. I am sure, either I am doing something wrong or I am missing something small. Please feel free to let me know if any further information is needed from my side I am thanking all in advance for your help

Paresh
  • 31
  • 2

0 Answers0