目標
於Nodejs、momgodb user authentication with JSON Web Tokens 專案中加入test機制
測試用戶註冊、登入、取得用戶資訊、刪除用戶功能
Package Dependence
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{
"name": "user_authentication_api",
"description": "api server",
"node-main": "./run.js",
"dependencies": {
"bcrypt-nodejs": "^0.0.3",
"body-parser": "^1.15.2",
"express": "^4.14.0",
"jwt-simple": "^0.5.0",
"morgan": "^1.7.0",
"moment": "^2.14.1",
"mongoose": "^4.6.1",
"passport": "^0.3.2",
"passport-jwt": "^2.1.0"
},
"devDependencies": {
"mocha": "^3.0.2",
"nodemon": "^1.9.1",
"supertest": "^2.0.0",
"should": "^11.1.0"
},
"scripts": {
"dev": "node dev.js",
"test": "./node_modules/.bin/mocha test",
"product": "node run.js"
},
"author": "will.chen",
"license": "ISC"
}
目錄結構
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "user_authentication_api", | |
"description": "api server", | |
"node-main": "./run.js", | |
"dependencies": { | |
"bcrypt-nodejs": "^0.0.3", | |
"body-parser": "^1.15.2", | |
"express": "^4.14.0", | |
"jwt-simple": "^0.5.0", | |
"morgan": "^1.7.0", | |
"moment": "^2.14.1", | |
"mongoose": "^4.6.1", | |
"passport": "^0.3.2", | |
"passport-jwt": "^2.1.0" | |
}, | |
"devDependencies": { | |
"mocha": "^3.0.2", | |
"nodemon": "^1.9.1", | |
"supertest": "^2.0.0", | |
"should": "^11.1.0" | |
}, | |
"scripts": { | |
"dev": "node dev.js", | |
"test": "./node_modules/.bin/mocha test", | |
"product": "node run.js" | |
}, | |
"author": "will.chen", | |
"license": "ISC" | |
} |
NodeJS_User_Authentication |-test |-routes |-users.js - 測試用戶API all.test.js - 測試入口
test/routes/users.js,註冊、登入取得token、根據token取得user info、刪除user
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* supertest是測試框架中用來模擬http行為的套件 | |
* should是一種表述性、可讀性很強的斷言庫,可擴充Object的property檢查回傳內容,屬於BDD風格 | |
*/ | |
let supertest = require('supertest'); | |
let should = require('should'); | |
module.exports = (app, username, displayName, password) => { | |
let request = supertest(app); | |
let initializeUrl = '/api/initialize'; | |
let usersUrl = '/api/users'; | |
let loginUrl = '/api/users/login'; | |
let meUrl = '/api/users/me'; | |
describe('initialize...', () => { | |
it('should response status 200 when initialize', function(done) { | |
this.timeout(10000); //set timeout limit | |
request.post(initializeUrl) | |
.set('Content-Type', 'application/json') | |
.expect(200) | |
.end(function(err, res) { | |
done(err); | |
}) | |
}) | |
}) | |
describe('signup...', () => { | |
it('should response status 200 when signup', function(done) { | |
this.timeout(10000); //set timeout limit | |
request.post(usersUrl) | |
.set('Content-Type', 'application/json') | |
.send({ | |
username: username, | |
displayName: displayName, | |
password: password, | |
}) | |
.expect(200) | |
.end(function(err, res) { | |
done(err); | |
}) | |
}) | |
}) | |
describe('login...', () => { | |
let token; | |
let userid; | |
before((done) => { //login and save token | |
request.post(loginUrl) | |
.set('Content-Type', 'application/json') | |
.send({ | |
username: username, | |
password: password | |
}) | |
.expect(200) | |
.end(function(err, res) { | |
token = res.body.token; | |
userid = res.body.uid; | |
done(err); | |
}) | |
}) | |
describe('get user info...', () => { | |
it('should response status 401 when not send with token', function(done) { | |
request.get(meUrl) | |
.expect(401) | |
.end(function(err, res) { | |
done(err); | |
}) | |
}) | |
it('should response status 200 and contains username、displayName when header has jwt token', function(done) { | |
request.get(meUrl) | |
.set('Authorization', token) | |
.expect(200) | |
.end(function(err, res) { | |
res.body.should.have.property('username'); | |
res.body.should.have.property('displayName'); | |
done(err); | |
}) | |
}) | |
}) | |
describe('delete user...', () => { | |
let resourceUrl; | |
before(function() { | |
resourceUrl = usersUrl + '/' + userid; | |
}) | |
it('should response success when deleting user exist', function(done) { | |
request.delete(resourceUrl) | |
.expect(200) | |
.end(function(err, res) { | |
res.body.should.have.property('success'); | |
res.body.success.should.equal(true); | |
done(err); | |
}) | |
}) | |
it('should response not found when user not exist', function(done) { | |
request.delete(resourceUrl) | |
.expect(404) | |
.end(function(err, res) { | |
res.body.message.should.equal('resource not found'); | |
done(err); | |
}) | |
}) | |
}) | |
}) | |
} |
test/all.test.js - 引用users.js測試案例,載入run.js進行API測試
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
global.__testBase = __dirname + '/'; | |
let app = require('../run'); | |
let userTest = require(__testBase + 'routes/users'); | |
describe('API Testing', () => { | |
userTest(app,'test','test','test'); | |
}) |
test/routes/users.js - 設計路由內的user test case,簡單的測試初始化、註冊、登入、取得登入者本身的資訊、刪除user
引入需要使用的套件
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* supertest是測試框架中用來模擬http行為的套件 | |
* should是一種表述性、可讀性很強的斷言庫,可擴充Object的property檢查回傳內容,屬於BDD風格 | |
*/ | |
let supertest = require('supertest'); | |
let moment = require('moment'); | |
let should = require('should'); |
宣告基本變數(測試路徑...等)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let request = supertest(app); | |
let initializeUrl = '/api/initialize'; | |
let usersUrl = '/api/users'; | |
let loginUrl = '/api/users/login'; | |
let meUrl = '/api/users/me'; |
測試初始化、註冊功能,這裡做個簡單的示範,僅驗證是否初始化成功
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
describe('initialize...', () => { | |
it('should response status 200 when initialize', function(done) { | |
this.timeout(10000); //set timeout limit | |
request.post(initializeUrl) | |
.set('Content-Type', 'application/json') | |
.expect(200) | |
.end(function(err, res) { | |
done(err); | |
}) | |
}) | |
}) | |
describe('signup...', () => { | |
it('should response status 200 when signup', function(done) { | |
this.timeout(10000); //set timeout limit | |
request.post(usersUrl) | |
.set('Content-Type', 'application/json') | |
.send({ | |
username: username, | |
displayName: displayName, | |
password: password, | |
}) | |
.expect(200) | |
.end(function(err, res) { | |
done(err); | |
}) | |
}) | |
}) |
登入後流程前置作業,由於取得user資訊及刪除user必須於登入後才能進行,因此我們必須先行登入並取得token跟user id 才能進行
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
describe('login...', () => { | |
let token; | |
let userid; | |
before((done) => { //login and save token | |
request.post(loginUrl) | |
.set('Content-Type', 'application/json') | |
.send({ | |
username: username, | |
password: password | |
}) | |
.expect(200) | |
.end(function(err, res) { | |
token = res.body.token; | |
userid = res.body.uid; | |
done(err); | |
}) | |
}) | |
} |
取得user資訊
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
describe('get user info...', () => { | |
it('should response status 401 when not send with token', function(done) { | |
request.get(meUrl) | |
.expect(401) | |
.end(function(err, res) { | |
done(err); | |
}) | |
}) | |
it('should response status 200 and contains username、displayName when header has jwt token', function(done) { | |
request.get(meUrl) | |
.set('Authorization', token) | |
.expect(200) | |
.end(function(err, res) { | |
res.body.should.have.property('username'); | |
res.body.should.have.property('displayName'); | |
done(err); | |
}) | |
}) | |
}) |
刪除user
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
describe('delete user...', () => { | |
let resourceUrl; | |
before(function() { | |
resourceUrl = usersUrl + '/' + userid; | |
}) | |
it('should response success when deleting user exist', function(done) { | |
request.delete(resourceUrl) | |
.expect(200) | |
.end(function(err, res) { | |
res.body.should.have.property('success'); | |
res.body.success.should.equal(true); | |
done(err); | |
}) | |
}) | |
it('should response not found when user not exist', function(done) { | |
request.delete(resourceUrl) | |
.expect(404) | |
.end(function(err, res) { | |
res.body.message.should.equal('resource not found'); | |
done(err); | |
}) | |
}) | |
}) |
留言
張貼留言