NestJS 在 e2e 测试中模拟 JWT 身份验证

Posted

技术标签:

【中文标题】NestJS 在 e2e 测试中模拟 JWT 身份验证【英文标题】:NestJS mock JWT authentication in e2e tests 【发布时间】: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 - 未经授权。

【问题讨论】:

这有帮助吗? ***.com/questions/53267536/testing-passport-in-nestjs 不幸的是,接受的答案中的实现不会模拟用户。相反,它会执行一个真正的身份验证请求.post('/auth/login'),这是我想避免的,因为我需要将凭据放入我的测试代码中。 我想我在身份验证代码中添加了process.env.NODE_ENV 签入以处理这种情况。 【参考方案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()

【讨论】:

以上是关于NestJS 在 e2e 测试中模拟 JWT 身份验证的主要内容,如果未能解决你的问题,请参考以下文章

NestJS jwt-passport 身份验证

如何使用 GRAPHQL 测试 e2e Nestjs API

NestJs JWT 身份验证返回 401

NestJs 使用 jwt 和私钥和公钥进行身份验证

e2e 如何与 guard nestjs

NestJs Passport jwt 未知策略