用Jest模拟jsonwebtoken模块

时间:2020-10-21 21:28:04

标签: node.js testing jestjs mocking jwt

我尝试开玩笑地模拟npm模块jsonwebtoken的验证功能。该函数返回一个已解码的令牌,但我想在单元测试中传递该函数的自定义返回。

我提出了明确的请求,要求在继续请求之前检查访问令牌的有效性。但是我想模拟令牌检查的时刻,以直接返回用户值。并轻松通过此步骤。我把代码的关注部分放到了你。

但是打字稿发给我这个错误: 属性'mockReturnValue'在类型'{上不存在(令牌:字符串,secretOrPublicKey:秘密,选项?:VerifyOptions | undefined):字符串|目的; (令牌:字符串,secretOrPublicKey:字符串|缓冲区| {键:字符串|缓冲区;密码:字符串;} | GetPublicKeyOrSecret,回调?:VerifyCallback |未定义):无效; (令牌:string,secretOrPublicKey:string | ... ...'。

因此,该模拟无法正常工作,我也不是很清楚。我在Jest.io上执行了模拟axios步骤,但似乎不适用于jsonwebtoken。

每个人都知道问题是什么,或者怎么开玩笑地模拟此jsonwebtoken模块?

users.test.ts

import jwt from 'jsonwebtoken'
    jest.mock('jwt')
    jwt.verify.mockReturnValue({
                    userId: String(member._id),
                    email: String(member.email),
                    permissionLevel: member.permissionLevel,
                    username: String(member.username),
                })

describe('### /GET users', () => {
            it('it should return 200 (Users List)', async (done) => {
                const res = await request(app).set('Authorization', 'Bearer').get('/users')
                expect(res.status).toBe(200)
            })
})

Validation.ts

public isAccessTokenValid = (req: Request, res: Response, next: NextFunction): void => {
        if (req.cryptedAccessToken) {
            try {
                req.accessToken = jwt.verify(req.cryptedAccessToken, ACCESS_TOKEN_SECRET)
                next()
            } catch (err) {
                res.status(498).send({ error: err.message })
            }
        } else res.status(401).send({ error: 'cryptedAccessToken field not present in request' })
    }

最诚挚的问候

2 个答案:

答案 0 :(得分:1)

这花了我一段时间,但我通过一些课程完成了这项工作。

  1. jest.mock('jsonwebtoken') 需要使用,并且必须放在spec文件的顶部,就在import jwt from 'jsonwebtoken'

    之后
  2. 这样做会模拟 jwt 的所有功能。就我而言,我只想模拟验证。这段代码解决了这个问题(替换上面的 (1))。

     import jwt from 'jsonwebtoken;
     jest.mock('jsonwebtoken', () => ({
     ...jest.requireActual('jsonwebtoken'), // import and retain the original functionalities
     verify: jest.fn().mockReturnValue({ foo: 'bar' }), // overwrite verify
     }));
    
  3. 然后我可以通过以下三种方式之一模拟验证:

a) 将其保留为默认模拟(返回 foo bar)

b) 使用 mockReturnValue,但我需要指定我要替换的重载 (thx @Gabriel)

  const verify = jwt.verify as jest.MockedFunction<
    (
      token: string,
      secretOrPublicKey: jwt.Secret,
      options?: jwt.VerifyOptions,
    ) => Record<string, unknown> | string
  >;
  verify.mockReturnValue({ verified: 'true' });

c) 使用模拟实现

 const verify = jest.spyOn(jwt, 'verify');
 verify.mockImplementation(() => () => ({ verified: 'true' }));

所有这些令人讨厌的事情是现在在规范文件中为所有描述/它模拟了验证。

答案 1 :(得分:0)

那是因为TypeScript“不知道”您已经模拟了模块,因此您可以尝试键入正确的类型

import jwt from 'jsonwebtoken'
const { verify } = jwt as jest.Mocked<typeof import('jsonwebtoken')>

verify.mockReturnValue({
  //...
})

(jwt as jest.Mocked<typeof import('jsonwebtoken')>).verify.mockReturnValue({
  //...
})