一步一步搭建react應用-node中使用 mocha + supertest + should 來寫單元測試

[一步一步構建一個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

相關文章
相關標籤/搜索