首页 > 解决方案 > 使用 jest 模拟 koa-jwt 中的默认中间件函数

问题描述

我正在使用koa-jwtwhich 反过来使用jsonwebtoken. 这是我的路由器实现:

index.ts

const jwt = require('koa-jwt');
...
// some other code
...

export const publicEndpoints = ['/', '/openapi.json', '/healthcheck'];

export default new Router<ApplicationState, ApplicationContext>()
  .use(configure)
  .use((ctx,next) => {
    console.log("REACH 02 opts",ctx,next);
    console.log("REACH 02 jwt", jwt);
  })
  .use(
    jwt({
      secret: customSecretLoader,
      audience: (jwksConfig.audience as unknown) as string,
      algorithms: ['RS256'],
    }).unless({ path: publicEndpoints })
  )
  // Public endpoints
  .use('/openapi.json', swagger)
  .use('/', helloworld)
  .use('/healthcheck', healthcheck)

  // Secure endpoints
  .get('/secure', helloworld)
  .middleware();

调用/secure应该通过调用jwt和传递令牌的中间件

我想测试每条安全路由,以确保它不会通过任何没有正确令牌的请求并通过那些有正确令牌的请求。

先验很简单,我只需要调用一个安全路由:

index.test.ts

  it('Unauthenticated secure request returns 401', async () => {
    const response = await request(server).get('/secure');
    expect(response.status).toEqual(401);
  });

然而,后者为了让它工作,我需要模拟jwt()函数调用并让它返回200,但问题是无论我在测试中写什么,我仍然调用koa-jwt.

*为了了解一些情况,这是koa-js我试图模拟的库https://github.com/koajs/jwt/blob/master/lib/index.js。它返回依次使用的middleware()调用verifyjsonwebtoken 在此处输入图像描述 在此处输入图像描述

模拟整个导出的函数

index.test.ts

`var jwt = require('koa-jwt');`

...
// some code
...

  it('Authenticated secure request returns 200', async () => {

    jwt = jest.fn(() => {
      Promise.resolve({
        status: 200,
        success: 'Token is valid'
      });
    });

    console.log("REACH 01 jwt", jwt);

    const response = await request(server).get('/secure');
    console.log("REACH RESPONSE",response);
    expect(response.status).toEqual(200);
  });

我在控制台日志中得到的输出是:

REACH 01 jwt function mockConstructor() {
        return fn.apply(this, arguments);
        }

这是我所期望的,但是当jwt()在输出中被击中时index.ts,我得到的是:

    REACH 02 jwt (opts = {}) => {
        const { debug, getToken, isRevoked, key = 'user', passthrough, tokenKey } = opts;
        const tokenResolvers = [resolveCookies, resolveAuthHeader];

        if (getToken && typeof getToken === 'function') {
            tokenResolvers.unshift(getToken);
        }

        const middleware = async function jwt(ctx, next) {
            let token;
            tokenResolvers.find(resolver => token = resolver(ctx, opts));
.....

我希望在嘲笑koa-jwt后我会在两个控制台日志中看到相同的输出。

我尝试了一些不同的东西,得到了相同的结果: - 在导出的默认函数中模拟中间件函数- 模拟其中koa-js 的依赖项koa-jsjsonwebtoken

我错过了什么?

标签: jwtkoa

解决方案


解决方案是在测试之外模拟整个模块:

import....

// some other code

jest.mock('koa-jwt', () => {
  const fn = jest.fn((opts) => // 1st level i.e. jwt()
  {
    const middlewareMock = jest.fn(async (ctx, next) => { // 2nd level i.e. middleware() 
      // Unreachable
    });
    // @ts-ignore
    middlewareMock.unless = jest.fn(() => jest.fn((ctx, next) => {
      next();
    })); // 4th level i.e. middleware().unless()
    return middlewareMock;
  });
  return fn;
});

... 

describe('routes: index', () => {
  // Testing each secure endpoint with authentication
  it('Authenticated requests to secure endpoints return 200', async () => {
    secureEndpoints.forEach(async (endpoint) => {
      const response = await request(server).get(endpoint);
      expect(response.status).toEqual(200);
    });
  });
});

推荐阅读