使用 jest 模拟 koa-jwt 中的默认中间件函数
mocking the default middleware function in koa-jwt using jest
我正在使用 koa-jwt
,而后者又使用 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
的中间件并传递token
我想测试每条安全路由,以确保它不会传递任何没有正确令牌的请求并传递正确令牌的请求。
之前很简单,我只需要调用一个安全路由:
index.test.ts
it('Unauthenticated secure request returns 401', async () => {
const response = await request(server).get('/secure');
expect(response.status).toEqual(401);
});
然而,后者,为了让它工作,我需要模拟 jwt()
函数调用并让它 return 200
但 问题 是无论我在测试中写了什么,我仍然调用 koa-jwt
.
的原始实现
*为了了解一些上下文,这是我试图模拟的 koa-js
库 https://github.com/koajs/jwt/blob/master/lib/index.js。它 returns middleware()
调用 verify
而后者又使用 jsonwebtoken
模拟整个导出函数
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-js
的依赖,即 jsonwebtoken
我错过了什么?
解决方案是在测试外部 模拟整个模块:
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);
});
});
});
我正在使用 koa-jwt
,而后者又使用 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
的中间件并传递token
我想测试每条安全路由,以确保它不会传递任何没有正确令牌的请求并传递正确令牌的请求。
之前很简单,我只需要调用一个安全路由:
index.test.ts
it('Unauthenticated secure request returns 401', async () => {
const response = await request(server).get('/secure');
expect(response.status).toEqual(401);
});
然而,后者,为了让它工作,我需要模拟 jwt()
函数调用并让它 return 200
但 问题 是无论我在测试中写了什么,我仍然调用 koa-jwt
.
*为了了解一些上下文,这是我试图模拟的 koa-js
库 https://github.com/koajs/jwt/blob/master/lib/index.js。它 returns middleware()
调用 verify
而后者又使用 jsonwebtoken
模拟整个导出函数
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-js
的依赖,即 jsonwebtoken
我错过了什么?
解决方案是在测试外部 模拟整个模块:
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);
});
});
});