【问题标题】:Testing Passport in NestJS在 NestJS 中测试 Passport
【发布时间】:2019-04-15 11:47:21
【问题描述】:

我正在尝试对具有来自 nestjs 护照模块的 AuthGuard 的路由进行 e2e 测试,但我真的不知道如何处理它。当我运行测试时,它说:

[ExceptionHandler] 未知身份验证策略“bearer”

我还没有嘲笑它,所以我想是因为这个,但我不知道该怎么做。

这是我目前所拥有的:

player.e2e-spec.ts

import { Test } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import { PlayerModule } from '../src/modules/player.module';
import { PlayerService } from '../src/services/player.service';
import { Repository } from 'typeorm';

describe('/player', () => {
  let app: INestApplication;
  const playerService = { updatePasswordById: (id, password) => undefined };

  beforeAll(async () => {
    const module = await Test.createTestingModule({
      imports: [PlayerModule],
    })
      .overrideProvider(PlayerService)
      .useValue(playerService)
      .overrideProvider('PlayerRepository')
      .useClass(Repository)
      .compile();

    app = module.createNestApplication();
    await app.init();
  });

  it('PATCH /password', () => {
    return request(app.getHttpServer())
      .patch('/player/password')
      .expect(200);
  });
});

player.module.ts

import { Module } from '@nestjs/common';
import { PlayerService } from 'services/player.service';
import { PlayerController } from 'controllers/player.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Player } from 'entities/player.entity';
import { PassportModule } from '@nestjs/passport';

@Module({
  imports: [
    TypeOrmModule.forFeature([Player]),
    PassportModule.register({ defaultStrategy: 'bearer' }),
  ],
  providers: [PlayerService],
  controllers: [PlayerController],
  exports: [PlayerService],
})
export class PlayerModule {}

【问题讨论】:

    标签: nestjs


    【解决方案1】:

    以下是基于 TypeORM 和 NestJs 的 passportjs 模块的身份验证 API 的 e2e 测试。 auth/authorize API 检查用户是否已登录。auth/login API 验证用户名/密码组合并在以下情况下返回 JSON Web 令牌 (JWT)查找成功。

    import { HttpStatus, INestApplication } from '@nestjs/common';
    import { Test } from '@nestjs/testing';
    import { TypeOrmModule } from '@nestjs/typeorm';
    import * as request from 'supertest';
    import { UserAuthInfo } from '../src/user/user.auth.info';
    import { UserModule } from '../src/user/user.module';
    import { AuthModule } from './../src/auth/auth.module';
    import { JWT } from './../src/auth/jwt.type';
    import { User } from '../src/entity/user';
    
    describe('AuthController (e2e)', () => {
      let app: INestApplication;
      let authToken: JWT;
    
      beforeAll(async () => {
        const moduleFixture = await Test.createTestingModule({
          imports: [TypeOrmModule.forRoot(), AuthModule],
        }).compile();
    
        app = moduleFixture.createNestApplication();
        await app.init();
      });
    
      it('should detect that we are not logged in', () => {
        return request(app.getHttpServer())
          .get('/auth/authorized')
          .expect(HttpStatus.UNAUTHORIZED);
      });
    
      it('disallow invalid credentials', async () => {
        const authInfo: UserAuthInfo = {username: 'auser', password: 'badpass'};
        const response = await request(app.getHttpServer())
          .post('/auth/login')
          .send(authInfo);
        expect(response.status).toBe(HttpStatus.UNAUTHORIZED);
      });
    
      it('return an authorization token for valid credentials', async () => {
        const authInfo: UserAuthInfo = {username: 'auser', password: 'goodpass'};
        const response = await request(app.getHttpServer())
          .post('/auth/login')
          .send(authInfo);
        expect(response.status).toBe(HttpStatus.OK);
        expect(response.body.user.username).toBe('auser');
        expect(response.body.user.firstName).toBe('Adam');
        expect(response.body.user.lastName).toBe('User');
        authToken = response.body.token;
      });
    
      it('should show that we are logged in', () => {
        return request(app.getHttpServer())
          .get('/auth/authorized')
          .set('Authorization', `Bearer ${authToken}`)
          .expect(HttpStatus.OK);
      });
    });
    

    请注意,由于这是一个端到端测试,它不使用模拟(至少我的端到端测试不使用 :))。希望这会有所帮助。

    【讨论】:

    • 它实际上是 JSON Web Token 我的朋友。
    • 测试顺序不可靠。我们最好把获取token的方法移到beforeAll
    【解决方案2】:

    您可以生成一个有效的令牌并将其发送到标头中以使用护照(jwt,...)进行身份验证:

    beforeAll(async () => {
        const moduleFixture: TestingModule = await Test.createTestingModule({
          imports: [AppModule],
        })
        
          .compile();
    
        productService = moduleFixture.get<ProductService>(ProductService);
        userService = moduleFixture.get<UsersService>(UsersService);
        authService = moduleFixture.get<AuthenticationService>(
          AuthenticationService,
        );
        app = moduleFixture.createNestApplication();
        await app.init();
      });
      afterAll(async () => {
        await app.close();
      });
    
      beforeEach(async () => {
        const signupResult = await authService.signup({
          email: 'test@test.com',
          name: 'test user',
          password: 'testpassword',
        });
        accessToken = signupResult.token.access_token;  // this line find a valid access token and you can pass this to your tests
      });
    

    将 access_token 传递给请求:

    it('should return 201 and return product', async () => {
          return request(app.getHttpServer())
            .post('/products')
            .set('Authorization', `Bearer ${accessToken}`)  // this is for Authentication
            .send({})
            .expect(201)
            .expect(({ body }) => {
              expect(body.id).toBeDefined();
            });
      });
    

    【讨论】:

      猜你喜欢
      • 2020-03-24
      • 2019-08-29
      • 2015-03-02
      • 2020-09-01
      • 1970-01-01
      • 2022-01-06
      • 1970-01-01
      • 2020-06-09
      • 2019-03-28
      相关资源
      最近更新 更多