我刚接触过password.js,并试图涵盖我的JWT策略的单元测试用例。谁能建议该怎么做?
// Setup JWT strategy for all requests
passport.use(
new JWTStrategy(
{
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: JWT_PRIVATE_KEY,
},
async (jwtPayload: any, done: any) => {
const isUser = jwtPayload.type === EntityType.User;
const model = isUser ? userModel : vendorModel;
try {
const document = await model.findOne({ _id: jwtPayload.id });
if (document) {
return done(null, jwtPayload);
} else {
return done(null, false);
}
} catch (err) {
return done(err, false);
}
},
),
);
答案 0 :(得分:0)
单元测试解决方案:
index.ts
:
import passport from 'passport';
import { Strategy as JWTStrategy, ExtractJwt } from 'passport-jwt';
import { userModel, vendorModel, EntityType } from './models';
const JWT_PRIVATE_KEY = 'secret 123';
passport.use(
new JWTStrategy(
{
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: JWT_PRIVATE_KEY,
},
async (jwtPayload: any, done: any) => {
console.log('123123');
const isUser = jwtPayload.type === EntityType.User;
const model = isUser ? userModel : vendorModel;
try {
const document = await model.findOne({ _id: jwtPayload.id });
if (document) {
return done(null, jwtPayload);
} else {
return done(null, false);
}
} catch (err) {
return done(err, false);
}
},
),
);
models.ts
:
export enum EntityType {
User = 'User',
}
export const userModel = {
async findOne(opts) {
return 'real user document';
},
};
export const vendorModel = {
async findOne(opts) {
return 'real vendor document';
},
};
index.test.ts
:
import { Strategy as JWTStrategy, ExtractJwt, VerifyCallback, StrategyOptions } from 'passport-jwt';
import passport from 'passport';
import { userModel, vendorModel } from './models';
jest.mock('passport-jwt', () => {
const mJWTStrategy = jest.fn();
const mExtractJwt = {
fromAuthHeaderAsBearerToken: jest.fn(),
};
return { Strategy: mJWTStrategy, ExtractJwt: mExtractJwt };
});
jest.mock('passport', () => {
return { use: jest.fn() };
});
describe('62125872', () => {
let verifyRef;
beforeEach(() => {
const mJwtFromRequestFunction = jest.fn();
(ExtractJwt.fromAuthHeaderAsBearerToken as jest.MockedFunction<
typeof ExtractJwt.fromAuthHeaderAsBearerToken
>).mockReturnValueOnce(mJwtFromRequestFunction);
(JWTStrategy as jest.MockedClass<any>).mockImplementation((opt: StrategyOptions, verify: VerifyCallback) => {
verifyRef = verify;
});
});
it('should verify using user model and call done with jwtpayload if user document exists', async () => {
const payload = { type: 'User', id: 1 };
const mDone = jest.fn();
jest.spyOn(userModel, 'findOne').mockResolvedValueOnce('mocked user document');
await import('./');
await verifyRef(payload, mDone);
expect(passport.use).toBeCalledWith(expect.any(Object));
expect(JWTStrategy).toBeCalledWith(
{ jwtFromRequest: expect.any(Function), secretOrKey: 'secret 123' },
expect.any(Function),
);
expect(ExtractJwt.fromAuthHeaderAsBearerToken).toBeCalledTimes(1);
expect(userModel.findOne).toBeCalledWith({ _id: 1 });
expect(mDone).toBeCalledWith(null, { type: 'User', id: 1 });
});
it("should verify using user model and call done with false if user document doesn't exist", async () => {
const payload = { type: 'User', id: 1 };
const mDone = jest.fn();
jest.spyOn(userModel, 'findOne').mockResolvedValueOnce('');
await import('./');
await verifyRef(payload, mDone);
expect(passport.use).toBeCalledWith(expect.any(Object));
expect(JWTStrategy).toBeCalledWith(
{ jwtFromRequest: expect.any(Function), secretOrKey: 'secret 123' },
expect.any(Function),
);
expect(ExtractJwt.fromAuthHeaderAsBearerToken).toBeCalledTimes(1);
expect(userModel.findOne).toBeCalledWith({ _id: 1 });
expect(mDone).toBeCalledWith(null, false);
});
// you can do the rest parts
});
单元测试结果:
PASS stackoverflow/62125872/index.test.ts
62125872
✓ should verify using user model and call done with jwtpayload if user document exists (11ms)
✓ should verify using user model and call done with false if user document doesn't exist (2ms)
-----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-----------|---------|----------|---------|---------|-------------------
All files | 85 | 83.33 | 60 | 84.21 |
index.ts | 92.86 | 75 | 100 | 92.31 | 24
models.ts | 66.67 | 100 | 33.33 | 66.67 | 6,11
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 3.716s, estimated 10s
答案 1 :(得分:0)
使用 supertest
验证完整周期
import request from 'supertest';
import express from 'express';
import jwt from 'jsonwebtoken'
export const createAuthToken = (userId) => {
const body = {
type: EntityType.User,
id: userId,
};
return jwt.sign(body, JWT_PRIVATE_KEY);
};
// this function should configure express app
const appLoader = async app => {
(await import('../app/loaders/express')).expressLoader({ app }); // express bindings and routes
await import('./'); // passport config
}
describe('passport-jwt auth', () => {
const app = express();
const token = createAuthToken('user1')
beforeAll(async () => {
await appLoader({ app });
});
it('should verify auth', async () => {
jest.spyOn(userModel, 'findOne').mockResolvedValueOnce('mocked user document');
await request(app)
.get('/protected-endpoint')
.set('Authorization', `Bearer ${token}`)
.expect(200);
});
it('should verify auth - failure', async () => {
await request(app)
.get('/protected-endpoint')
.set('Authorization', `Bearer wrong-token`)
.expect(401);
});
});