带你入门带你飞Ⅱ 使用Mocha + Chai + SuperTest测试Restful API in node.js
目录
1. 简介
2. 准备开始
3. Restful API测试实战
Example 1 - GET
Example 2 - Post
Example 3 - Put
Example 4 - Delete
4. Troubleshooting
5. 参考文档
简介
经过上一篇文章的介绍,相信你已经对mocha, chai有一定的了解了, 本篇主要讲述如何用supertest来测试nodejs项目中的Restful API, 项目基于express框架。
SuperTest 是 SuperAgent一个扩展, 一个轻量级 HTTP AJAX 请求库.
SuperTest provides high-level abstractions for testing node.js API endpoint responses with easy to understand assertions.
准备开始
npm安装命令
npm install supertest
nodejs项目文件目录结构如下
├── config
│ └── config.json
├── controllers
│ └── dashboard
│ └── widgets
│ └── index.js
├── models
│ └── widgets.js
├── lib
│ └── jdbc.js
├── package.json
└── test
└── controllers
└── dashboard
└── widgets
└── index_IntegrationTest.js
测试代码写在index_IntegrationTest.js这个文件中
Restful API测试实战
测试依赖库
var express = require('express');
var kraken = require('kraken-js');
var request = require('supertest');
var chai = require('chai');
var assert = chai.assert;
##转载注明出处:http://www.cnblogs.com/wade-xu/p/4673460.html
Example 1 - GET
Controller/dashboard/widgets/index.js
var _widgets = require('../../../models/widgets.js');
module.exports = function(router) {
router.get('/', function(req, res) {
_widgets.getWidgets(req.user.id)
.then(function(widgets){
return res.json(widgets);
})
.catch(function(err){
return res.json ({
code: '000-0001',
message: 'failed to get widgets:'+err
});
});
});
};
测试代码:
var kraken = require('kraken-js');
var express = require('express');
var request = require('supertest');
var aweb = require('acxiom-web');
var chance = new(require('chance'))();
var chai = require('chai');
var assert = chai.assert;
describe('/dashboard/widgets', function() {
var app, mock;
before(function(done) {
app = express();
app.on('start', done);
app.use(kraken({
basedir: process.cwd(),
onconfig: function(config, next) {
//some config info
next(null, config);
}
}));
mock = app.listen(1337);
});
after(function(done) {
mock.close(done);
});
it('get widgets', function(done) {
request(mock)
.get('/dashboard/widgets/')
.set('Accept', 'application/json')
.expect(200)
.expect('Content-Type', 'application/json; charset=utf-8')
.end(function(err, res) {
if (err) return done(err);
assert.isArray(res.body, 'return widgets object');
done();
});
});
});
Example 2 - Post
被测代码:
router.post('/', function(req, res) {
_widgets.addWidget(req.user.id, req.body.widget)
.then(function(widget){
return res.json(widget);
})
.catch(function(err){
return res.json ({
code: '000-0002',
message: 'failed to add widget:' + err
});
});
});
测试代码:
it('add widgets', function(done) {
var body = {
widget: {
type: 'billing',
color: 'blue',
location: {
x: '1',
y: '5'
}
}
};
request(mock)
.post('/dashboard/widgets/')
.send(body)
.expect(200)
.expect('Content-Type', /json/)
.end(function(err, res) {
if (err) return done(err);
assert.equal(res.body.type, 'billing');
assert.equal(res.body.color, 'blue');
done();
});
});
##转载注明出处:http://www.cnblogs.com/wade-xu/p/4673460.html
Example 3 - Put
被测代码
router.put('/color/:id', function(req, res) {
_widgets.changeWidgetColor(req.params.id, req.body.color)
.then(function(status){
return res.json(status);
})
.catch(function(err){
return res.json ({
code: '000-0004',
message: 'failed to change widget color:' + err
});
});
});
测试代码
describe('change widget color', function() {
var id = '';
before(function(done) {
var body = {
widget: {
type: 'billing',
color: 'blue',
location: {
x: '1',
y: '5'
}
}
};
request(mock)
.post('/dashboard/widgets/')
.send(body)
.expect(200)
.expect('Content-Type', /json/)
.end(function(err, res) {
if (err) return done(err);
id = res.body.id;
done();
});
});
it('change widget color to white', function(done) {
var body = {
color: 'white'
};
request(mock)
.put('/dashboard/widgets/color/' + id)
.send(body)
.expect(200)
.expect({
status: 'success'
})
.expect('Content-Type', /json/)
.end(function(err, res) {
if (err) return done(err);
done();
});
});
});
在这个测试case中,前提是要先create 一个widget, 拿到id之后你才可以针对这个刚创建的widget修改, 所以在it之前用了 before 做数据准备。
Example 4 - Delete
被测代码
router.delete('/:id', function(req, res) {
_widgets.deleteWidget(req.user.id, req.params.id)
.then(function(status){
return res.json(status);
})
.catch(function(err){
return res.json ({
code: '000-0003',
message: 'failed to delete widget:' + err
});
});
});
测试代码
describe('delete widget', function() {
var id = '';
before(function(done) {
var body = {
widget: {
type: 'billing',
color: 'blue',
location: {
x: '1',
y: '5'
}
}
};
request(mock)
.post('/dashboard/widgets/')
.send(body)
.expect(200)
.expect('Content-Type', /json/)
.end(function(err, res) {
if (err) return done(err);
id = res.body.id;
done();
});
});
it('delete a specific widget', function(done) {
request(mock)
.del('/dashboard/widgets/' + id)
.expect(200)
.expect('Content-Type', /json/)
.end(function(err, res) {
if (err) return done(err);
assert.deepEqual(res.body, {
status: 'success'
});
done();
});
});
});
注意这里用的是del 不是 delete, Supertest提供的delete方法是del, 不是delete
##转载注明出处:http://www.cnblogs.com/wade-xu/p/4673460.html
测试结果如下:

Troubleshooting
1. 当你用request().delete() 时报错TypeError: undefined is not a function
换成request().del()
参考文档
Mocha: http://mochajs.org/
Chai: http://chaijs.com/
SuperTest: https://www.npmjs.com/package/supertest
感谢阅读,如果您觉得本文的内容对您的学习有所帮助,您可以点击右下方的推荐按钮,您的鼓励是我创作的动力。
##转载注明出处:http://www.cnblogs.com/wade-xu/p/4673460.html
带你入门带你飞Ⅱ 使用Mocha + Chai + SuperTest测试Restful API in node.js的更多相关文章
- 使用 TypeScript & mocha & chai 写测试代码实战(17 个视频)
使用 TypeScript & mocha & chai 写测试代码实战(17 个视频) 使用 TypeScript & mocha & chai 写测试代码实战 #1 ...
- 带你入门带你飞Ⅰ 使用Mocha + Chai + Sinon单元测试Node.js
目录 1. 简介 2. 前提条件 3. Mocha入门 4. Mocha实战 被测代码 Example 1 Example 2 Example 3 5. Troubleshooting 6. 参考文档 ...
- #单元测试#以karma+mocha+chai 为测试框架的Vue webpack项目(二)
学习对vue组件进行单元测试,先参照官网编写组件和测试脚本. 1.简单的组件 组件无依赖,无props 对于无需导入任何依赖,也没有props的,直接编写测试案例即可. /src/testSrc/si ...
- #单元测试#以karma+mocha+chai 为测试框架的Vue webpack项目(一)
目标: 为已有的vue项目搭建 karma+mocha+chai 测试框架 编写组件测试脚本 测试运行通过 抽出共通 一.初始化项目 新建项目文件夹并克隆要测试的已有项目 webAdmin-web 转 ...
- node.js入门基础
内容: 1.node.js介绍 2.node.js内置常用模块 3.node.js数据交互 一.node.js介绍 (1)node.js特点 与其他语言相比,有以下优点: 对象.语法和JavaScri ...
- 极简 Node.js 入门 - Node.js 是什么、性能有优势?
极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...
- DTSE Tech Talk | 第10期:云会议带你入门音视频世界
摘要:本期直播主题是<云会议带你入门音视频世界>,华为云媒体服务产品部资深专家金云飞,与开发者们交流华为云会议在实时音视频行业中的集成应用,帮助开发者更好的理解华为云会议及其开放能力. 本 ...
- 可能是史上最强大的js图表库——ECharts带你入门
PS:之前的那篇博客Highcharts——让你的网页上图表画的飞起 ,评论中,花儿笑弯了腰 和 StanZhai 两位仁兄让我试试 ECharts ,去主页看到<Why ECharts ?&g ...
- 史上最强大的js图表库——ECharts带你入门(转)
出处:http://www.cnblogs.com/zrtqsk/p/4019412.html PS:之前的那篇博客Highcharts——让你的网页上图表画的飞起 ,评论中,花儿笑弯了腰 和 Sta ...
随机推荐
- CSS外边距margin上下元素重叠
CSS外边距margin上下元素重叠 转载:http://www.gaoyouyou.com/view/77.htm 两个或多个块级盒子的垂直相邻边界会重合.结果的边界宽度是相邻边界宽度中最大的值.如 ...
- IOS照片颠倒分析及移动/页面端的处理策略和思路
前言: 前几天, 写了一篇关于IOS手机上传照片颠倒的技术分析文章: IOS照片颠倒分析及PHP服务端的处理. 不过其思路是从服务器来进行处理的, 这种做法相当普遍. 今天来讲述下, 如何从移动端/页 ...
- Angularjs scope
$scope: var myapp = angular.module('myapp', []); myapp .controller('parent', function ($scope,$timeo ...
- 第十章 嵌入式Linux的调用技术
HAL是建立在Linux驱动之上的一套程序库,这套程序库并不属于Linux内核,而属于linux内核层之上的应用层. 在本章中还介绍了为什么要在Android中加入HAL,统一硬件的调用接口,由于H ...
- 数组map()方法和filter()方法及字符串startsWith(anotherString)和endsWith(anotherString)方法
map方法的作用不难理解,"映射"嘛,也就是原数组被"映射"成对应新数组 var newArr = arr.map(function() {});例子: var ...
- 如何用selenium webdriver 捕获js error
### 问题 捕捉页面上js error ### 解决办法 从Selenium webdriver log 中解析 # -*- coding:utf8 -*- import unittest from ...
- lua Getter&Setter简单实现
lua是一门简单的语言,不带类和属性封装,但可以使用lua强大的元表模拟实现: class.lua local type = type local rawset = rawset local setm ...
- Struts2向值栈中压入属性的方式
Struts2在初始化Action的时候会先向值栈中压入一个action对象,里面包含了各个属性,这些属性是怎么被压进去的?或者说是根据什么来压入的?直到2016年5月5日才理解,原来是在初始化act ...
- Java Concurrent之 AbstractQueuedSynchronizer
ReentrantLock/CountDownLatch/Semaphore/FutureTask/ThreadPoolExecutor的源码中都会包含一个静态的内部类Sync,它继承了Abstrac ...
- .gitignore的多级目录配置
在子目录下仍然可以建立.gitignore文件以用于忽略子目录的文件