[一步一步构建一个react应用-开篇](https://segmentfault.com/a/11...前端
git地址node
mocha 是一个node单元测试框架,相似于前端的jasmine,语法也相近react
supertest 用来测试node接口的库git
should nodejs断言库,可读性很高github
npm install mocha should supertest --save-dev
项目根目录下新建test文件夹,movies.spec.jsmongodb
package.json中数据库
"scripts": { "start": "pm2 start ecosystem.config.js", "test": "mocha --watch" //监听 test文件下的全部文件 },
这里咱们来测试一个添加一条电影的接口npm
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字段json
大致代码segmentfault
/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