【问题标题】:NestJS mock JWT authentication in e2e testsNestJS 在 e2e 测试中模拟 JWT 身份验证
【发布时间】:2019-12-28 22:48:02
【问题描述】:

我想在我的 NestJS e2e(集成)测试中模拟 JWT 身份验证。我在我的业务逻辑中使用注入的令牌数据,我不想在我的测试代码中插入凭据。

我根据Nest authentication docs 实现了 JWT 身份验证。我在示例中使用了与 @User 装饰器类似的装饰器,并在我的业务逻辑中使用了有关 User 对象的信息。

@Post()
async myPostEndpoint(@Body() body: PostBody, @User() user: MyUser){
    // do stuff using user properties
}

在使用Nest testing docs 中所示的超测试测试我的应用程序时,我不想发出真正的身份验证请求,因为我需要在我的版本控制系统中保留凭据。

我希望能够覆盖提供者以返回测试用户。但想不通。

我尝试覆盖AuthServicevalidateClientlogin 以使用overrideProvider + useClass/useFactory/useValue 返回默认用户,如Nest testing docs 所示。我还尝试了覆盖 JwtStrategyLocalStrategy 中的方法,但请求仍然返回 401 - 未经授权。

【问题讨论】:

  • 不幸的是,接受的答案中的实现不会模拟用户。相反,它会执行一个真正的身份验证请求.post('/auth/login'),这是我想避免的,因为我需要将凭据放入我的测试代码中。
  • 我想我在身份验证代码中添加了process.env.NODE_ENV 签入以处理这种情况。

标签: typescript unit-testing authentication mocking nestjs


【解决方案1】:

在您的 overrideGuard(AuthGuard('jwt')).useValue() 中,您可以向您的 canActivate() 函数添加功能,如下所示:

canActivate (context: ExecutionContext) => {
  const req = context.switchToHttp().getRequest();
  req.user = myCustomUserObject;
  return true;
}

其中myCustomUserObject 是服务器要处理的req.user 的预期值。

【讨论】:

  • 嘿嘿,我试过你的答案,但我得到“无法设置未定义的属性'用户'”。 “req”值未定义... :(
  • 我做了同样的事情,没有像@MirceaBaicu 所说的那样得到任何错误,但是在该API上注册的下一个守卫没有检测到属性user on req,因此禁止。有什么线索吗?
  • 为什么不使用测试用户并创建 JWT,我认为 e2e 测试应该接近真实应用程序
  • 从技术上讲,这将是更好的选择@MADforFUNandHappy,但由于问题是专门关于嘲笑守卫的,我想我会回答这个问题。
  • 非常感谢,我试图模拟 AuthGuard 本身,但它没有成功。
【解决方案2】:

一些具体情况,我们需要动态覆盖canActivate(例如覆盖不同的'users') 所以我只是像这样开玩笑地嘲笑了“jsonwebtoken”模块

jest.mock('jsonwebtoken', () => ({
  verify: jest.fn((token, secretOrKey, options, callback) => {
    callback(null, {
      payload: {
        email: 'any@email.com',
        sub: 1,
      },
      header: 'header',
      signature: 'signature',
    });
  }),
}));

【讨论】:

    【解决方案3】:

    对于使用 GraphQL 的人,这是我所做的:

    const module: TestingModule = await Test.createTestingModule({
          imports: [AppModule],
        })
          .overrideGuard(JwtAuthGuard)
          .useValue({
            canActivate: (context: ExecutionContext) => {
              const ctx = GqlExecutionContext.create(context)
              ctx.getContext().req.user = { user_id: "abc123" } // Your user object
              return true
            },
          })
          .compile()
    

    【讨论】:

      猜你喜欢
      • 2019-03-28
      • 2021-03-02
      • 2020-08-13
      • 2019-09-13
      • 1970-01-01
      • 1970-01-01
      • 2015-06-01
      • 2021-06-04
      • 2023-03-31
      相关资源
      最近更新 更多