一步一步搭建react应用-node中使用 mocha + supertest + should 来写单元测试

git地址

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,594评论 18 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,567评论 18 399
  • 嗯。。。知道还有2天就要考理论然而并没有看书的我的内心是崩溃的。。。 但是人生除了考试总有点别的什么不是嘛 今天和...
    橣檬不酸阅读 133评论 0 0
  • 17年2月23星期五 偏冷 我们珍惜一个人,一定是感动过;我们放弃一个人,一...
    甘海连阅读 232评论 0 0
  • 有朋友私信问我会不会结婚,我想起曾经听过的一句话: “别去期待婚姻,我更希望是你爱的那个人,来赋予婚姻本身的意义”...
    藤原拓冬阅读 716评论 5 11