Node.js 如何在NestJS中对控制器应用保护进行单元测试?

Node.js 如何在NestJS中对控制器应用保护进行单元测试?,node.js,typescript,jestjs,nestjs,Node.js,Typescript,Jestjs,Nestjs,我已经在NestJS中配置了一个控制器,我想检查是否设置了适当的防护装置——有人举过一个例子来说明如何做到这一点吗 这个(节略的)示例作为一个应用程序可以正常工作,所以我只需要了解测试指南 您会注意到,在用户测试中,有一些测试我正在调用Reflect.getMetadata。我想要的是这样的东西——当我在\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

我已经在NestJS中配置了一个控制器,我想检查是否设置了适当的防护装置——有人举过一个例子来说明如何做到这一点吗

这个(节略的)示例作为一个应用程序可以正常工作,所以我只需要了解测试指南

您会注意到,在用户测试中,有一些测试我正在调用
Reflect.getMetadata
。我想要的是这样的东西——当我在
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>元数据上检查它时,这是一个函数

User.controller.ts

@Controller('/api/user')
导出类用户控制器{
@UseGuard(AuthGuard('jwt'))
@得到()
用户(@Request()请求){
返回请求用户;
}
}
User.controller.spec.ts

description('User Controller',()=>{
//根据cli生成器在每次设置之前
描述(“#用户”,()=>{
在每个之前(()=>{
//这就是我如何检查@Get()装饰器是否正确应用的方法-我在为u___)卫士寻找一些东西__
expect(Reflect.getMetadata('path',controller.user)).toBe('/');
expect(Reflect.getMetadata('method',controller.user)).toBe(RequestMethod.GET);
});
它('应该返回用户',()=>{
常数要求={
用户:“userObj”,
};
expect(controller.user(req)).toBe(req.user);
});
});
});

无论如何,您不需要测试框架提供的装饰器是否也设置了您期望的内容。这就是为什么框架首先要对它们进行测试。不过,如果您想检查装饰程序是否实际设置了预期的元数据

如果您只是想测试guard,那么可以直接实例化GuardClass,并通过提供
ExecutionContext
对象来测试其
canActivate
方法。该示例使用一个库为您创建模拟对象,但其思想是您可以创建一个类似

const context = {
  switchToHttp: () => ({
    getRequest: jest.fn(),
    getResponse: jest.fn(),
  })
}

其中
getRequest
getResponse
返回HTTP请求和响应对象(或至少部分)。要仅使用此对象,您还需要像使用任何对象一样使用
,以避免Typescript抱怨过多。

我意识到这并不是您想要的答案,但基于@Jay McDoniel的答案,我使用以下方法测试了自定义装饰器在控制器函数上的存在性(尽管我不能100%确定这是否是对非定制防护进行测试的正确方法)

和控制器

it('should ensure the JwtAuthGuard is applied to the controller', async () => {
  const guards = Reflect.getMetadata('__guards__', MyController)
  const guard = new (guards[0])

  expect(guard).toBeInstanceOf(JwtAuthGuard)
});

这并不是我真正想要做的。我希望确保为该方法设置了守卫装饰器。我不在乎装饰器在下面做什么(出于您提到的原因),我已经对守卫本身进行了测试。如果这是“经典”Express app,我可以测试中间件是否应用于路由,这正是我在这里试图实现的,但对于decorators,我不太确定我是否理解您当时试图实现的目标。第一个链接显示的测试显示了元数据在类和类方法上的正确设置,这是如何实现的是“设定”。如果你想在调用路由时测试这一点,那么你需要设置supertest来调用路由。也许我不明白你想做什么。是的,e2e测试是实现这一点的一个选项。这很可能是一种更合适的方法。我给出的示例确实检查了设置了rect元数据,但这是因为我无法找到更好的方法来测试@Get decorator的应用(我愿意接受建议)。我试图实现的是一个测试,以确保设置了适当的防护措施-我更喜欢通过单元测试而不是e2e来完成,因为它将出现在覆盖率报告中,但这不是一个交易突破。看起来元数据的反射仍然是您在这里的最佳选择。在上面的示例中,您可以进行类似
exp的测试ect(Reflect.getMetadata(“”、UserController.user)).toEqual(mixinuthGuard)
。mixinuthGuard是mixin
AuthGuard('jwt')
生成的类。这将断言该保护应用于UserController.user方法(即GET/api/user路由)将是正确的guardGreat,谢谢。正如我在OP中所说的,我并不是在测试装饰器的功能之后,只是在应用了适当的配置。因为我们在代码中依赖它,我认为这应该是单元测试的一部分
it('should ensure the JwtAuthGuard is applied to the user method', async () => {
  const guards = Reflect.getMetadata('__guards__', MyController.prototype.user)
  const guard = new (guards[0])

  expect(guard).toBeInstanceOf(JwtAuthGuard)
});
it('should ensure the JwtAuthGuard is applied to the controller', async () => {
  const guards = Reflect.getMetadata('__guards__', MyController)
  const guard = new (guards[0])

  expect(guard).toBeInstanceOf(JwtAuthGuard)
});