nod*_*oob 14 testing api mocha.js node.js
TL; DR - 测试使用JWT进行身份验证的Node API(Express)中的资源的方法是什么,只有授予用户名/密码登录权限的令牌?
我对测试很陌生,想得到一些建议.最终目标是拥有一个经过全面测试的API,然后开始学习如何将其连接到持续集成解决方案.
使用的技术
API信息
API具有各种资源 - 其具体细节对于此查询并不重要,但为了简单起见,我们只是假装它是无处不在的Todo应用程序.
保存在数据库中的每个单独资源都与一个用户相关联.
API使用JWT在各种资源端点上进行身份验证.令牌本身包含唯一的用户ID,该用户ID是针对Mongo数据库中的资源存储的.要获取令牌本身,需要用户首先注册(返回令牌),然后登录以获取新令牌.
假装代码.
我将简化下面的代码,而不是使用任何环境配置等...
app.js
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'));
});
Run Code Online (Sandbox Code Playgroud)
./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;
Run Code Online (Sandbox Code Playgroud)
./api/users/routes.js
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;
Run Code Online (Sandbox Code Playgroud)
./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);
Run Code Online (Sandbox Code Playgroud)
./api/todos/model.js
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);
Run Code Online (Sandbox Code Playgroud)
我省略了一些示例代码,以保持其简洁.
例如,用户的控制器将包含模型,其功能将:
该待办事项的控制器就可以做同样的事情-只是通过猫鼬蒙哥的数据交互,但查询总是包括用户ID设置为特定的(例如)待办事项与认证用户(通过JWT认证)相关联.
测试难题
我如何使用Mocha,Chai和SuperTest的组合来测试这样的东西?
我可以吗:
在开发时,与使用某种CI工具进行部署时,测试将如何在本地进行(我在学习中还没有这样做)?
任何帮助将不胜感激,我希望我已经给出了上面的虚拟数据/代码足够的信息:/
在测试期间,您通常会模拟您的 mongo DB(类似于 )mongo-mock。这样,您不需要运行实际的数据库来运行测试(您不是在测试数据库,而是在测试您的代码)。
在测试期间,您将替换为mongodb,mongo-mock然后运行测试。要获取令牌,您需要使用/me有效的模拟凭据发布到 URL,该端点将返回令牌,然后您可以在下次调用时使用该令牌来测试其他端点。
在令牌方面,我通常在请求开始时在输入其他端点之前检查它。(我没有使用过护照,但想法是):
app.use(validate_jwt_middleware);
app.use('/users', userRouter);
Run Code Online (Sandbox Code Playgroud)
这样,如果令牌无效,则它对整个网站都无效,而不仅仅是您的部分。
另外,我没有使用 SuperTest,而是 chai-http,所以我无法帮助你了解你的具体情况。
希望这可以帮助,
| 归档时间: |
|
| 查看次数: |
2400 次 |
| 最近记录: |