NodeJs学习笔记(四)---单元测试

sailsjs框架用了一段时间了,感觉如果功能复杂了,非常难以处理,想用一下单元测试,看是否能解决问题。

sailsjs的官方文档使用的是mocha,我搜索了一些资料,主要参考了朴灵的《深入浅出nodejs》的单元测试一章、sailsjs的官方文档以及github上的一个例子https://github.com/bredikhin/sailsjs-mocha-testing-barrels-fixtures-example

1)系统环境如下

Windows 8.1 X64

nodejs 0.12.1

sailsjs  0.11.0

2)安装过程

需要安装mocha和should,mocha是测试框架,should是一个断言,也可以使用原生的assert,supertest是用来测试http请求的,这里用来测试controller

npm install mocha -g

npm install should

npm install supertest

其中mocha的主页为http://mochajs.org/,should的主页是https://www.npmjs.com/package/should,可以从这些网站找到相关的文档。

mocha是安装为全局命令的,可以直接在命令行运行mocha,其参数较多,可以用mocha --help查看一下参数。

3)目录和文件准备

./myApp
├── api
├── assets
├── ...
├── test
│  ├── unit
│  │  ├── controllers
│  │  │  └── UserController.test.js
│  │  ├── models
│  │  │  └── User.test.js
│  │  └── ...
│  ├── fixtures
│  ├── ...
│  ├── bootstrap.test.js
│  └── mocha.opts
└── views

首先在根目录下建立test目录,然后一次建立test\unit\controllers和test\unit\models目录。

然后在test下建立文件bootstrap.test.js,这个文件是用来启动sailsjs程序的,也可以说是配置环境的,内容如下

var Sails = require(‘sails‘),

sails;

before(function (done) {

Sails.lift({

log : {

level : ‘error‘   //指定错误级别,避免出现调试输出,这主要是用来调试controller

}

}, function (err, server) {

sails = server;

if (err)

return done(err);

// here you can load fixtures, etc.

done(err, sails);

});

});

after(function (done) {

var done_called = false;

Sails.lower(function () {

if (!done_called) {

done_called = true;

setTimeout(function () {

sails.log.debug("inside app.lower, callback not called yet. calling.");

done();

}, 1000);

} else {

sails.log.debug("inside app.lower, callback already called.");

}

});

});

需要注意的是,after()和官方文档的不一致,因为会出现done()调用多次的问题,所以我参考了网上的一个资源,增加了等待。

4)测试控制器(controller)

在test\unit\controllers下建立UserController.test.js,内容如下

var request = require(‘supertest‘);

var should = require(‘should‘);

describe(‘UsersController‘, function () {

describe(‘#login()‘, function () {

it(‘should get 1‘, function (done) {

request(sails.hooks.http.app)

.get(‘/user/login?login_code=12345678901&user_password=111111‘)

.end(function (err, results) {

should(results.res.body.result).be.exactly(1);

done();

});

});

});

});

这里用的是BDD的风格,我比较喜欢这种方式,也可以采用TDD的风格,感觉都差不多

上面的代码也很简单,对/user/login?login_code=12345678901&user_password=111111发起请求,根据返回内容进行判断,这里要注意一下,返回的信息要多于通常的返回,比如我的返回是类似于{result: 1, desc:‘登录成功‘}之类的,但是supertest返回的要多得多,所以用result.res.body.result才能得到result值,也可以将信息打印出来看一下,不过需要注意的是因为前面设置了log:{level: ‘error‘},可以看不到输出,可以将error改成info,再试一下。

5)运行测试

mocha -t 10000 test/bootstrap.test.js test/unit/**/*.test.js

也可以在package.json中的scripts下增加npm命令,如下

"scripts": {

"start": "node app.js",

"debug": "node debug app.js",

"test": "mocha -t 10000 test/bootstrap.test.js test/unit/**/*.test.js"

},

这样就可以直接运行npm test执行测试了。

需要说明一下, -t 10000代表每个测试的执行时间增加到10秒,默认是2秒,在我的系统上无法返回,会出现错误,可能我的机器太慢了吧。

如果用户名密码正确,则返回

1 passing (7s)

如果出现错误,则返回

0 passing (6s)

1 failing

1) UsersController #login() should get 1:

Uncaught AssertionError: expected 0 to be 1

+ expected - actual

-0

+1

at Test.<anonymous> (D:\work\nodejs\KangfuMobile\test\unit\controllers\Use rController.test.js:13:40)

at net.js:1392:10

所以用来测试controller是非常简单的,

6)测试逻辑,在test\unit\models建立User.test.js,内容为

var should = require(‘should‘);

var bcrypt = require(‘bcrypt‘);

describe(‘用户表‘, function () {

describe(‘查找用户信息‘, function () {

it(‘应该检查用户表是否没有这个用户了‘, function (done) {

User.find({

user_code : ‘12345678901‘

}).exec(function (err, results) {

should(results.length).be.exactly(1);

done();

});

});

});

describe(‘查找用户名密码‘, function () {

it(‘应该检查密码是否录入错误,或者密码加密系统出现错误‘, function (done) {

User.findOne({

user_code : ‘12345678901‘

}).exec(function (err, user) {

var user_password = ‘111111‘;

var user_password_o = user.user_password;

user_password_o = "$2a$" + user_password_o.substr(4);

bcrypt.compare(user_password, user_password_o, function (err, comp) {

should(comp).be.exactly(true);

done();

});

});

});

});

});

上面有两个测试,一个是查看是否存在且只有一个用户名为“12345678901”的用户,第二个是查看其密码是否正确。

运行测试命令,得到如下结果,如果没有用户,则会出现下面的错误:

2 passing (6s)

3 failing

1) UsersController #login() should get 1:

Uncaught AssertionError: expected 0 to be 1

+ expected - actual

-0

+1

at Test.<anonymous> (D:\work\nodejs\KangfuMobile\test\unit\controllers\Use rController.test.js:13:40)

at net.js:1392:10

2) 用户表 查找用户信息 应该检查用户表是否没有这个用户了:

Uncaught AssertionError: expected 0 to be 1

+ expected - actual

-0

+1

at D:\work\nodejs\KangfuMobile\test\unit\models\Users.test.js:10:31

at readableAddChunk (_stream_readable.js:163:16)

at Socket.Readable.push (_stream_readable.js:126:10)

at TCP.onread (net.js:529:20)

3) 用户表 查找用户名密码 应该检查密码是否录入错误,或者密码加密系统出现错误:

Uncaught TypeError: Cannot read property ‘user_password‘ of undefined

at D:\work\nodejs\KangfuMobile\test\unit\models\Users.test.js:21:31

at readableAddChunk (_stream_readable.js:163:16)

at Socket.Readable.push (_stream_readable.js:126:10)

at TCP.onread (net.js:529:20)

通过上面就可以查看是否出现了错误,并检查可能的问题,如果修改正确了,就会

5 passing (6s)

7)基本来说,单元测试的基本内容就清楚了,不过想要更好的使用,还需要学会如何使用断言,比如should,还需要学习supertest的语法,mocha的BDD风格倒是非常简单,就是

describe(‘测试内容‘,function(){

describe(‘测试内容1‘, function(){

it(‘需要注意什么‘, function(done){

//做测试

done();

})

})

})

如果用过async框架,就会对done()的使用非常熟悉了,这主要是用来处理异步问题的,等到done()返回才算测试结束了。

should的使用非常简单,可以参考官方文档,也可以看看牛人写的例子:https://github.com/shouldjs/examples

时间: 2024-07-29 16:30:56

NodeJs学习笔记(四)---单元测试的相关文章

NodeJS学习笔记四

Generator简介 基本概念 Generator函数有多种理解角度.从语法上,首先可以把它理解成,Generator函数是一个状态机,封装了多个内部状态. 执行Generator函数会返回一个遍历器对象,也就是说,Generator函数除了状态机,还是一个遍历器对象生成函数.返回的遍历器对象,可以依次遍历Generator函数内部的每一个状态. 形式上,Generator函数是一个普通函数,但是有两个特征.一是,function命令与函数名之间有一个星号:二是,函数体内部使用yield语句,

nodejs学习笔记四(模块化、在npm上发布自己的模块)

模块化: 1.系统模块:  http.querystring.url 2.自定义模块 3.包管理器 [系统模块] Assert      断言:肯定确定会出现的情况使用断言 stabiltry: locked   稳定性,锁定,再也不会改了 C/C++ ADDons      c的扩展:关键性的函数可以用c来写,提高稳定性 child Processes        子进程 Cluster                     集群 Command Line Opation        

Caliburn.Micro学习笔记(四)----IHandle&lt;T&gt;实现多语言功能

Caliburn.Micro学习笔记(四)----IHandle<T>实现多语言功能 说一下IHandle<T>实现多语言功能 因为Caliburn.Micro是基于MvvM的UI与codebehind分离, binding可以是双向的所以我们想动态的实现多语言切换很是方便今天我做一个小demo给大家提供一个思路 先看一下效果 点击英文  变成英文状态点chinese就会变成中文                          源码的下载地址在文章的最下边 多语言用的是资源文件建

代码管理工具 --- git的学习笔记四《重新整理git(1)》

1.创建版本库 mkdir  创建目录 cd  地址,到该地址下 pwd 显示当前目录 1.创建目录 $ mkdir startGit $ cd startGit $ pwd 显示当前目录 或者cd到桌面,然后再创建目录 2.初始化版本库 $ git init 初始化仓库 提示信息:Initialized empty Git repository in /Users/xingzai/Desktop/startGit/.git/ 建立一个空的git仓库在/Users/xingzai/Desktop

Linux学习笔记四:Linux的文件搜索命令

1.文件搜索命令  which 语法:which [命令名称] 范例:$which ls  列出ls命令所在目录 [[email protected] ~]$ which ls alias ls='ls --color=auto' /bin/ls 另外一个命令:whereis [名称名称],也可以列出命令所在目录. [[email protected] ~]$ whereis ls ls: /bin/ls /usr/share/man/man1/ls.1.gz /usr/share/man/ma

小猪的数据结构学习笔记(四)

小猪的数据结构学习笔记(四) 线性表之静态链表 --转载请注明出处:coder-pig 本章引言: 在二,三中中我们分别学习了顺序表中的线性表与单链表,线性表有点类似于 我们前面所学的数组,而单链表使用的最多的是指针,这里问个简单的问题, 如果是在以前没有指针的话,前辈先人们怎么实现单链表呢?大家思考下! 没有指针,那么用什么来代替呢?前辈先人们非常机智,想出了使用下标+游标的方式 来实现单链表的效果!也就是今天要讲的--静态链表! 当然你也可以直接跳过本章,因为有了单链表就没有必要用静态链表了

Swift学习笔记四:数组和字典

最近一个月都在专心做unity3d的斗地主游戏,从早到晚,最后总算是搞出来了,其中的心酸只有自己知道.最近才有功夫闲下来,还是学习学习之前的老本行--asp.net,现在用.net做项目流行MVC,而不是之前的三层,既然技术在更新,只能不断学习,以适应新的技术潮流! 创建MVC工程 1.打开Visual studio2012,新建MVC4工程 2.选择工程属性,创建MVC工程 3.生成工程的目录 App_Start:启动文件的配置信息,包括很重要的RouteConfig路由注册信息 Conten

nodejs学习笔记(基于v7.4.0)

nodejs学习笔记 一.buffer: 全局对象(单例   Buffer.from   Buffer.alloc   Buffer.allocUnsafe ) 编码类型 描述 ascii 仅仅用于7位ascall数据编码,速度快,如果设置了将会剥离高位 utf8 多字节的编码的Unicode字符,网页文档大部分默认都为它. utf16le 小端编码的Unicode字符,2或者4个字节 ucs2 utf16le的别名 base64 Base64是网络上最常见的用于传输8Bit字节代码的编码方式之

nodejs学习笔记_nodejs和PHP在基础架构上的差别--共享状态的并发

绝大多数对于Node.js的讨论都把关注点放在了处理高并发能力上,做开发的时候一定要明确node内部做出的权衡,以及node应用性能好的原因. node 为javascript引入了一个复杂的概念,:共享状态的并发. node採用一个长期执行的进程 而php在apache中会产生多个进程 例如以下图所看到的: 代码验证: PHP: <?php $i = 0; $i++; echo $i nodejs: var http = require('http'); var i=0; http.creat

nodejs学习笔记之安装、入门

由于项目需要,最近开始学习nodejs.在学习过程中,记录一些必要的操作和应该注意的点. 首先是如何安装nodejs环境?(我用的是windows 7环境,所以主要是windows 7的例子.如果想看linux下的安装可以参考http://www.cnblogs.com/meteoric_cry/archive/2013/01/04/2844481.html) 1. nodejs提供了一些安装程序,可以去官网(http://nodejs.org/download/)按照自己的机器进行下载,下载完