带你入门带你飞Ⅱ 使用Mocha + Chai + SuperTest测试Restful API in node.js
目录
1. 简介
2. 准备开始
3. Restful API测试实战
Example 1 - GET
Example 2 - Post
Example 3 - Put
Example 4 - Delete
4. Troubleshooting
5. 参考文档
简介
经过上一篇文章的介绍,相信你已经对mocha, chai有一定的了解了, 本篇主要讲述如何用supertest来测试nodejs项目中的Restful API, 项目基于express框架。
SuperTest 是 SuperAgent一个扩展, 一个轻量级 HTTP AJAX 请求库.
SuperTest provides high-level abstractions for testing node.js API endpoint responses with easy to understand assertions.
准备开始
npm安装命令
npm install supertest
nodejs项目文件目录结构如下
├── config │ └── config.json ├── controllers │ └── dashboard │ └── widgets │ └── index.js ├── models │ └── widgets.js ├── lib │ └── jdbc.js ├── package.json └── test └── controllers └── dashboard └── widgets └── index_IntegrationTest.js
测试代码写在index_IntegrationTest.js这个文件中
Restful API测试实战
测试依赖库
var express = require('express'); var kraken = require('kraken-js'); var request = require('supertest'); var chai = require('chai'); var assert = chai.assert;
##转载注明出处:http://www.cnblogs.com/wade-xu/p/4673460.html
Example 1 - GET
Controller/dashboard/widgets/index.js
var _widgets = require('../../../models/widgets.js');
module.exports = function(router) {
router.get('/', function(req, res) {
_widgets.getWidgets(req.user.id)
.then(function(widgets){
return res.json(widgets);
})
.catch(function(err){
return res.json ({
code: '000-0001',
message: 'failed to get widgets:'+err
});
});
});
};
测试代码:
var kraken = require('kraken-js'); var express = require('express'); var request = require('supertest'); var aweb = require('acxiom-web'); var chance = new(require('chance'))(); var chai = require('chai'); var assert = chai.assert; describe('/dashboard/widgets', function() { var app, mock; before(function(done) { app = express(); app.on('start', done); app.use(kraken({ basedir: process.cwd(), onconfig: function(config, next) { //some config info next(null, config); } })); mock = app.listen(1337); }); after(function(done) { mock.close(done); }); it('get widgets', function(done) { request(mock) .get('/dashboard/widgets/') .set('Accept', 'application/json') .expect(200) .expect('Content-Type', 'application/json; charset=utf-8') .end(function(err, res) { if (err) return done(err); assert.isArray(res.body, 'return widgets object'); done(); }); }); });
Example 2 - Post
被测代码:
router.post('/', function(req, res) { _widgets.addWidget(req.user.id, req.body.widget) .then(function(widget){ return res.json(widget); }) .catch(function(err){ return res.json ({ code: '000-0002', message: 'failed to add widget:' + err }); }); });
测试代码:
it('add widgets', function(done) { var body = { widget: { type: 'billing', color: 'blue', location: { x: '1', y: '5' } } }; request(mock) .post('/dashboard/widgets/') .send(body) .expect(200) .expect('Content-Type', /json/) .end(function(err, res) { if (err) return done(err); assert.equal(res.body.type, 'billing'); assert.equal(res.body.color, 'blue'); done(); }); });
##转载注明出处:http://www.cnblogs.com/wade-xu/p/4673460.html
Example 3 - Put
被测代码
router.put('/color/:id', function(req, res) { _widgets.changeWidgetColor(req.params.id, req.body.color) .then(function(status){ return res.json(status); }) .catch(function(err){ return res.json ({ code: '000-0004', message: 'failed to change widget color:' + err }); }); });
测试代码
describe('change widget color', function() { var id = ''; before(function(done) { var body = { widget: { type: 'billing', color: 'blue', location: { x: '1', y: '5' } } }; request(mock) .post('/dashboard/widgets/') .send(body) .expect(200) .expect('Content-Type', /json/) .end(function(err, res) { if (err) return done(err); id = res.body.id; done(); }); }); it('change widget color to white', function(done) { var body = { color: 'white' }; request(mock) .put('/dashboard/widgets/color/' + id) .send(body) .expect(200) .expect({ status: 'success' }) .expect('Content-Type', /json/) .end(function(err, res) { if (err) return done(err); done(); }); }); });
在这个测试case中,前提是要先create 一个widget, 拿到id之后你才可以针对这个刚创建的widget修改, 所以在it之前用了 before 做数据准备。
Example 4 - Delete
被测代码
router.delete('/:id', function(req, res) { _widgets.deleteWidget(req.user.id, req.params.id) .then(function(status){ return res.json(status); }) .catch(function(err){ return res.json ({ code: '000-0003', message: 'failed to delete widget:' + err }); }); });
测试代码
describe('delete widget', function() { var id = ''; before(function(done) { var body = { widget: { type: 'billing', color: 'blue', location: { x: '1', y: '5' } } }; request(mock) .post('/dashboard/widgets/') .send(body) .expect(200) .expect('Content-Type', /json/) .end(function(err, res) { if (err) return done(err); id = res.body.id; done(); }); }); it('delete a specific widget', function(done) { request(mock) .del('/dashboard/widgets/' + id) .expect(200) .expect('Content-Type', /json/) .end(function(err, res) { if (err) return done(err); assert.deepEqual(res.body, { status: 'success' }); done(); }); }); });
注意这里用的是del 不是 delete, Supertest提供的delete方法是del, 不是delete
##转载注明出处:http://www.cnblogs.com/wade-xu/p/4673460.html
测试结果如下:
Troubleshooting
1. 当你用request().delete() 时报错TypeError: undefined is not a function
换成request().del()
参考文档
Mocha: http://mochajs.org/
Chai: http://chaijs.com/
SuperTest: https://www.npmjs.com/package/supertest
感谢阅读,如果您觉得本文的内容对您的学习有所帮助,您可以点击右下方的推荐按钮,您的鼓励是我创作的动力。
##转载注明出处:http://www.cnblogs.com/wade-xu/p/4673460.html