跳到主要內容

Nodejs API Test


目標


Package Dependence


{
"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"
}
view raw package.json hosted with ❤ by GitHub
目錄結構

NodeJS_User_Authentication 
 |-test 
  |-routes 
   |-users.js - 測試用戶API 
  all.test.js - 測試入口

test/routes/users.js,註冊、登入取得token、根據token取得user info、刪除user

/**
* 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測試

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


引入需要使用的套件

/**
* supertest是測試框架中用來模擬http行為的套件
* should是一種表述性、可讀性很強的斷言庫,可擴充Object的property檢查回傳內容,屬於BDD風格
*/
let supertest = require('supertest');
let moment = require('moment');
let should = require('should');
view raw requires.js hosted with ❤ by GitHub

宣告基本變數(測試路徑...等)

let request = supertest(app);
let initializeUrl = '/api/initialize';
let usersUrl = '/api/users';
let loginUrl = '/api/users/login';
let meUrl = '/api/users/me';
view raw variables.js hosted with ❤ by GitHub

測試初始化、註冊功能,這裡做個簡單的示範,僅驗證是否初始化成功

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 才能進行

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);
})
})
}
view raw login.js hosted with ❤ by GitHub

取得user資訊

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);
})
})
})
view raw userinfo.js hosted with ❤ by GitHub

刪除user

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);
})
})
})
view raw delete.user.js hosted with ❤ by GitHub

留言

這個網誌中的熱門文章

C#資料庫操作(新增、修改、刪除、查詢)

java西元民國轉換_各種不同格式