Node.js 如何测试使用JWT身份验证的节点API(通过用户登录获取令牌)
TL;DR-在使用JWT进行身份验证的节点API(Express)中测试资源的方法是什么?令牌本身仅授予用户名/密码登录 我对测试有点陌生,希望得到一些建议。最终目标是拥有一个经过充分测试的API,然后开始学习如何将其连接到持续集成解决方案 正在使用的技术Node.js 如何测试使用JWT身份验证的节点API(通过用户登录获取令牌),node.js,api,testing,mocha.js,Node.js,Api,Testing,Mocha.js,TL;DR-在使用JWT进行身份验证的节点API(Express)中测试资源的方法是什么?令牌本身仅授予用户名/密码登录 我对测试有点陌生,希望得到一些建议。最终目标是拥有一个经过充分测试的API,然后开始学习如何将其连接到持续集成解决方案 正在使用的技术 我已经在节点中使用Express编写了一个API Mongo是数据库 猫鼬用作ODM jsonwebtoken包用于创建/验证令牌 Passport用于在路由上轻松添加用户身份验证作为快速中间件 API信息 API有各种各样的资源——这些
- 我已经在节点中使用Express编写了一个API
- Mongo是数据库李>
- 猫鼬用作ODM李>
- jsonwebtoken包用于创建/验证令牌
- Passport用于在路由上轻松添加用户身份验证作为快速中间件
var express = require('express');
var app = express();
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var passport = require('passport');
mongoose.connect('mongodb://localhost/somedatabasename');
app.set('port', process.env.PORT || 3000);
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(passport.initialize());
// ... Passport JWT Strategy goes here - omitted for simplicity ...
var userRouter = require('./api/users/routes');
app.use('/users', userRouter);
var todoRouter = require('./api/todos/routes');
app.use('/todos', todoRouter);
app.listen(app.get('port'), function() {
console.log('App now running on http://localhost:' + app.get('port'));
});
./api/todos/routes.js
var router = require('express').Router();
var controller = require('./controller');
var passport = require('passport');
router.route('/')
.all(passport.authenticate('jwt', { session: false}))
.get(controller.getAll)
.post(controller.create);
router.route('/:id')
.all(passport.authenticate('jwt', { session: false}))
.get(controller.getOne)
.put(controller.update)
.delete(controller.delete);
module.exports = router;
var router = require('express').Router();
var controller = require('./controller');
var passport = require('passport');
router.route('/')
// User signup
.post(controller.create);
router.route('/me')
// User Login
.post(passport.authenticate('local', { session: false}), controller.login)
// Get current user's data
.get(passport.authenticate('jwt', { session: false}), controller.getOne)
// Update current user's data
.put(passport.authenticate('jwt', { session: false}), controller.update)
// Delete current user
.delete(passport.authenticate('jwt', { session: false}), controller.delete);
module.exports = router;
/api/users/routes.js
var router = require('express').Router();
var controller = require('./controller');
var passport = require('passport');
router.route('/')
.all(passport.authenticate('jwt', { session: false}))
.get(controller.getAll)
.post(controller.create);
router.route('/:id')
.all(passport.authenticate('jwt', { session: false}))
.get(controller.getOne)
.put(controller.update)
.delete(controller.delete);
module.exports = router;
var router = require('express').Router();
var controller = require('./controller');
var passport = require('passport');
router.route('/')
// User signup
.post(controller.create);
router.route('/me')
// User Login
.post(passport.authenticate('local', { session: false}), controller.login)
// Get current user's data
.get(passport.authenticate('jwt', { session: false}), controller.getOne)
// Update current user's data
.put(passport.authenticate('jwt', { session: false}), controller.update)
// Delete current user
.delete(passport.authenticate('jwt', { session: false}), controller.delete);
module.exports = router;
./api/users/model.js
var mongoose = require('mongoose');
var bcrypt = require('bcrypt');
var UserSchema = new mongoose.Schema({
username: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
}
});
// ... for simplicity imagine methods here to
// - hash passwords on a pre save hook using bcrypt
// - compare passwords using bcrypt when logging in
module.exports = mongoose.model('User', UserSchema);
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var momentSchema = new Schema({
title: {
type: String
},
// Bunch of other fields here...
_user: {
type: Schema.Types.ObjectId,
ref: 'User'
}
});
module.exports = mongoose.model('Moment', momentSchema);
./api/todos/model.js
var mongoose = require('mongoose');
var bcrypt = require('bcrypt');
var UserSchema = new mongoose.Schema({
username: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
}
});
// ... for simplicity imagine methods here to
// - hash passwords on a pre save hook using bcrypt
// - compare passwords using bcrypt when logging in
module.exports = mongoose.model('User', UserSchema);
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var momentSchema = new Schema({
title: {
type: String
},
// Bunch of other fields here...
_user: {
type: Schema.Types.ObjectId,
ref: 'User'
}
});
module.exports = mongoose.model('Moment', momentSchema);
为了保持简洁,我省略了一些示例代码
例如,用户的控制器将包括模型及其功能:
- 控制器。创建-注册新用户(返回令牌)
- 控制器。登录-在Passport Local确认用户名/密码组合后,返回有效令牌
- controller.getOne-根据从JWT令牌检索到的用户ID,使用Mongoose从Mongo返回用户数据
- 控制器。更新-使用Mongoose更新Mongo中的用户数据
- 控制器。删除-使用Mongoose删除Mongo中的用户数据
- 在Mongo中创建一个测试数据库,测试中的连接字符串是否不同?这意味着保存数据库中存储的实际数据以供测试
- 以某种方式模拟数据,而根本不使用测试数据库?但是,如何处理用户保存/登录以检索令牌
如果您能提供任何帮助,我将不胜感激。我希望我已经提供了足够的关于上述虚拟数据/代码的信息:/在测试期间,您通常会模拟mongo DB(类似于
mongo mock
。这样,您就不需要运行实际的数据库来运行测试(您不是在测试数据库,而是在测试代码)
在测试期间,您将使用mongo mock
替换mongodb
,然后运行测试。要获取令牌,您需要使用有效的模拟凭据发布到/me
URL,该端点将返回令牌,然后在下次调用时使用该令牌测试其他端点
在令牌方面,我通常在请求开始时检查它,然后再进入其他端点(我没有使用passport,但想法是):
这样,如果令牌无效,那么它对整个站点无效,而不仅仅是您的部分
另外,我没有使用SuperTest,而是使用http,因此我无法帮助您了解具体情况
希望这能有所帮助,嗨!你明白了吗?我也在尝试实现这种测试。