[一步一步構建一個react應用-開篇](https://segmentfault.com/a/11…
mocha 是一個node單元測試框架,類似於前端的jasmine,語法也相近
supertest 用來測試node介面的庫
should nodejs斷言庫,可讀性很高
-
搭建
npm install mocha should supertest --save-dev
專案根目錄下新建test資料夾,movies.spec.js
package.json中
"scripts": {
"start": "pm2 start ecosystem.config.js",
"test": "mocha --watch" //監聽 test檔案下的所有檔案
},
-
介面描述
這裡我們來測試一個新增一條電影的介面
method: POST
api: /api/movies
document: {
"title": `movie0`,
"thumb": "public/p1075586949.jpg",
"actors": [
"河正宇",
"金允石",
"鄭滿植"
],
"type": [
"動作",
"犯罪"
],
"instruct": `instruct...`,
"time": "2010-12-22(韓國)",
}
這裡電影資訊會儲存到movies集合中,型別資訊儲存在types集合中
需要注意的是如果多條電影有相同的type,則同一個電影型別在collection中只存一次,但會inc count欄位
大體程式碼
/routes/movies.js
const MoviesModel = require(`../models/movies_model`)
const CONFIG = require(`../config/config`)
function callback(err, docs, res, next) {
if (err) {
next(err)
return
}
res.json({
code: CONFIG.ERR_OK,
data: docs
})
}
router.post(`/`, function (req, res, next) {
MoviesModel.addMovies(req.body, (err, docs) => {
callback(err, docs, res, next)
})
});
/models/movies_model.js
const TypeModel = require(`./type_model`)
class MoviesModel{
addMovies(data, callback) {
const types = data.type
DB.connect().then((db, err) => {
TypeModel.addTypes(types, db) //儲存分類
this.insertOne(db, data, callback)
}).catch(e => {
callback(e)
})
}
}
/models/type_model.js
class Type{
addTypes(typesArr, db) {
const Types = db.collection(`types`)
typesArr.forEach(item => {
Types.update({
`type_name`: item
}, {
`$inc`: { count: 1 }
}, { upsert: true })
})
}
}
-
測試
測試中我們錄入兩條電影資訊,兩條的type欄位中會有一個相同的型別
我們要驗證的結論:
兩條電影都成功錄入,types集合中有三條document,”動作”的count是2,另兩條count是1
當前環境是test時,使用測試資料庫
/config/db.js
let db_name=`Movies`
if(process.env.NODE_ENV==`test`){
db_name=`Movies_test`
}
const url = f(`mongodb://%s:%s@localhost:3307/${db_name}?authMechanism=%s`, user, pwd, authMechanism)
測試資料
const movieInfo = {
"title": `movie0`,"thumb": "public/p1075586949.jpg",
"actors": [
"河正宇",
],
"type": [
"動作",
"犯罪"
],
"instruct": `instruct...`,"time": "2010-12-22(韓國)",
}
const movieInfo1 = {
"title": `movie1`,"thumb": "public/p1075586949.jpg",
"actors": [
"河正宇",
],
"type": [
"動作",
"愛情"
],
"instruct": `instruct...`,"time": "2010-12-22(韓國)",
}
測試程式碼
process.env.NODE_ENV = `test` //執行時,會將當前環境設定為test,連線資料庫時使用Movies_test庫,如上
const should = require(`should`)
const request = require(`supertest`)
const app = require(`../app`)
describe(`Movies Test`,()=>{
describe(`POST /movies`,()=>{
//每個it語句執行開始之前會插入資料
beforeEach(function (done) {
request(app) //啟動node服務
.post(`/api/movies`).send(movieInfo).then(() => {
return request(app).post(`/api/movies`).send(movieInfo1)
}).then(res => {
done()
})
})
//每個it語句執行完之後會清除表資料
afterEach(function (done) {
MoviesModel.remove(() => {
TypeModel.remove(() => {
done()
})
})
})
//測試錄入成功
it(`add movie and get the added movie`, function (done) {
request(app)
.get(`/api/movies`)
.end((er, res) => {
should(res.body.data).have.length(2)
should(res.body.data[0]).have.property(`title`, `movie1`)
done()
})
})
//型別已經存在的就不在存了
it(`repeat type not saved,will only increment count`, function (done) {
request(app)
.get(`/api/types`)
.then(res => {
should(res.body.data).have.length(3)
should(res.body.data[0]).have.property(`count`, 2) //"動作"的count是2
should(res.body.data[1]).have.property(`count`, 1)
should(res.body.data[2]).have.property(`count`, 1)
done()
})
})
})
})
詳細完整的對每個介面的測試見 test