【问题标题】:How e2e with guard nestjse2e 如何与 guard nestjs
【发布时间】:2020-02-10 01:16:59
【问题描述】:

我想使用nestjs 对一个名为/users 的端点进行e2e,但出现错误。我对如何让警卫通过测试感到疑惑。

第一个错误

Nest 无法解析 UserModel (?) 的依赖关系。请确保 索引 [0] 处的参数 DatabaseConnection 在 MongooseModule 上下文。

第二个错误

预期 200“OK”,得到 401“Unauthorized”

App.module

@Module({
  imports: [
    MongooseModule.forRootAsync({
      imports: [ConfigModule],
      useFactory: async (configService: ConfigService) => ({
        uri: configService.mongoUri,
        useNewUrlParser: true,
      }),
      inject: [ConfigService],
    }),
    GlobalModule,
    UsersModule,
    AuthModule,
    PetsModule,
    RestaurantsModule,
    ConfigModule,
  ],
  controllers: [],
  providers: [],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(TokenDataMiddleware)
      .forRoutes({ path: '*', method: RequestMethod.ALL });
  }
}

用户服务

@Injectable()
export class UsersService {
  constructor(
    @InjectModel('User') private readonly userModel: Model<UserDocument>,
    private readonly utilsService: UtilsService,
    private readonly configService: ConfigService,
  ) { }
async getAllUsers(): Promise<UserDocument[]> {
    const users = this.userModel.find().lean().exec();
    return users;
  }
}

控制器

@Controller('users')
export class UsersController {
    constructor(private readonly usersService: UsersService, private readonly utilsService: UtilsService) { }
    @Get()
    @ApiBearerAuth()
    @UseGuards(JwtAuthGuard)
    async users() {
        const users = await this.usersService.getAllUsers();
        return users;
    }

e2e 文件

describe('UsersController (e2e)', () => {
  let app: INestApplication;
  beforeAll(async () => {
    const testAppModule: TestingModule = await Test.createTestingModule({
      imports: [AppModule, GlobalModule,
        UsersModule,
        AuthModule,
        PetsModule,
        RestaurantsModule,
        ConfigModule],
      providers: [],
    }).compile();

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

  it('GET all users from API', async () => {
    // just mocked users;
    const users = getAllUsersMock.buildList(2);
    const response = await request(app.getHttpServer())
      .get('/users')
      .expect(200);
  });

  afterAll(async () => {
    await app.close();
  });
});

【问题讨论】:

    标签: javascript node.js typescript jestjs nestjs


    【解决方案1】:

    在单元测试中,您测试单个单元(服务、控制器等),这意味着您导入一个单元并模拟其所有依赖项。然而,在 e2e 测试中,您想要测试您的整个应用程序,因此您应该导入根模块 (AppModule) 而不是单个单元或模块。有时您可能想要模拟应用程序的特定部分,例如数据库或第 3 方 API;你可以用overrideProvider 等来做到这一点。

    在您的情况下,您可能缺少从您的AppModule 导入的MongooseModuleforRoot。导入 AppModule,而不是重组应用程序的某些部分:

    await Test.createTestingModule({
          imports: [AppModule],
        }).compile()
          .overrideProvider(HttpService)
          .useValue(httpServiceMock);
    

    如果您的 API 受到保护,您需要对其进行身份验证。您可以通过编程方式创建 JWT,也可以使用您的 API。我假设您在以下示例中有一个用于身份验证的端点:

    const loginResponse = await request(app.getHttpServer())
      .post('/auth/login')
      .send({ username: 'user', password: '123456' })
      .expect(201);
    // store the jwt token for the next request
    const { jwt } = loginResponse.body;
    
    await request(app.getHttpServer())
      .get('/users')
      // use the jwt to authenticate your request
      .set('Authorization', 'Bearer ' + jwt)
      .expect(200)
      .expect(res => expect(res.body.users[0])
        .toMatchObject({ username: 'user' }));
    

    【讨论】:

    • 您好,感谢您的回答,我用您的更改更新了问题(它有效),但保留我关于模拟 jwt 令牌的问题以通过 JwtAuthGuard。谢谢!
    • @anthonywillismuñoz 查看我的编辑。由于您的 API 受到保护,因此 401 错误符合预期。测试未经身份验证的请求无法访问您的 API 实际上很好。要测试受保护的资源,您必须设置 Authorization 标头,请参见示例。此外,您不需要导入所有模块。 导入 AppModule。它本身将导入所有其他模块。
    • @Kim Kern 什么是 httpServiceMock?我遇到了同样的问题,无法理解
    • @MegaRoks 看看这个关于如何创建模拟的线程:stackoverflow.com/a/55366343/4694994
    猜你喜欢
    • 2020-10-28
    • 2022-12-22
    • 2019-11-15
    • 2022-12-24
    • 1970-01-01
    • 2021-02-24
    • 2022-10-06
    • 2021-10-12
    • 2021-02-25
    相关资源
    最近更新 更多