目錄
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
