node第三方模块should说明


原文:http://cnpmjs.org/package/should

assert是用于编写单元测试的断言库。should其实和assert的作用一样,它包装了assert,改变了书写风格。

should库扩展了Object.prototype,额外提供了".should"语法。一旦引入了should,即“var should = require('should');”,那么当前js文件内的所有继承至Object的对象都可以.should。如下所示例:


var should = require('should');     //引入了你就可以用Object.should了
//被测试的目标对象
var user = {
    name: 'tj'
  , pets: ['tobi', 'loki', 'jane', 'bandit']};

user.should.have.property('name', 'tj');
user.should.have.property('pets').with.lengthOf(4);

// 如果目标对象没有继承至Object,那就换一种方式使用:should(user).have.property('name', 'tj');

// null就没有继承至Objectshould(null).not.be.ok;

someAsyncTask(foo, function(err, result){
  should.not.exist(err);
  should.exist(result);
  result.bar.should.equal(foo);});

安装

should库需要额外安装:$ npm install should --save-dev

浏览器端将should包下的should.js引入到前台页面,即可和后端一样使用。


Static should and assert module

should的静态方法

should提供了一系列的静态方法,这些方法可以对非Object对象使用。它们和assert的基本方法其实是一样的。

可以只熟悉should的方法。这里不用看,晃一眼即可

assert.fail(actual, expected, message, operator) // just write wrong should assertion
assert(value, message), assert.ok(value, [message]) // should(value).okassert.equal(actual, expected, [message]) // should(actual).eql(expected, [message])assert.notEqual(actual, expected, [message]) // should(actual).not.eql(expected, [message])
assert.deepEqual(actual, expected, [message]) // should(actual).eql(expected, [message])
assert.notDeepEqual(actual, expected, [message]) // should(actual).not.eql(expected, [message])
assert.strictEqual(actual, expected, [message]) // should(actual).equal(expected, [message])
assert.notStrictEqual(actual, expected, [message]) // should(actual).not.equal(expected, [message])
assert.throws(block, [error], [message]) // should(block).throw([error])assert.doesNotThrow(block, [message]) // should(block).not.throw([error])
assert.ifError(value) // should(value).Error (to check if it is error) or should(value).not.ok (to check that it is falsy)

.not

.not 对当前的断言取反。

.any

.any和array.some方法类似,他可以接受多个参数或者数组,只要其中一个满足断言,即可。

.any和.not一起使用则会出错。


Assertions 断言

每一个should断言都返回一个被should.js包装过的对象,所以他可以形成链式语法,但是有一些断言,比如.length,.property等将被断言的对象改变成了其属性值。

。而且在“链”中,可以使用下面等方便理解的词,这些词其实对should的断言一点实际影响都没有,注意,没有.or。

.an, .of, .a, .and, .be, .have, .with, .is, .which.

user.should.be.an.instanceOf(Object).and.have.property('name', 'tj');
//其实就是user.should.instanceOf(Object).property('name', 'tj');


user.pets.should.be.instanceof(Array).and.have.lengthOf(4);
//其实就是user.pets.should.instanceof(Array).lenthOf(4);


.ok

断言当前的对象为真(==true),注意不是恒等,('', null, undefined, 0 , NaN 等都不ok)

注意不能对null,underfined使用ok,比如: undefined.should.not.be.ok;

为了测试是否为null,可以这样:(err === null).should.be.true;


.true

断言当前对象是否恒等true

.false

断言当前对象是否恒等true

false.should.be.false;
(0).should.not.be.false;


.eql(otherValue)

断言当前对象是否等于某个值,这过程会隐式转换类型,而且即使只有值相等即可。

[1,2,3].should.eql([1,2,3]);
// 下面的例子隐式转换了类型
[1, 2, 3].should.eql({ '0': 1, '1': 2, '2': 3 });


.equal(otherValue) and .exactly(otherValue)


断言当前对象是否与另一对象相同,===,恒等,用exactly比较好理解


(4).should.equal(4);
'test'.should.equal('test');
[1,2,3].should.not.equal([1,2,3]);
(4).should.be.exactly(4);


.startWith(str)

断言一个字符串的开始部分是另一个字符串
'foobar'.should.startWith('foo');
'foobar'.should.not.startWith('bar');


.endWith(str)

//断言一个字符串的结束部分是另一个字符串
'foobar'.should.endWith('bar');
'foobar'.should.not.endWith('foo');


.within(from, to)

断言一个数字,在某一个范围之内(<= to and >= from):

user.age.should.be.within(5, 50);
(5).should.be.within(5, 10).and.within(5, 5);


.approximately(num, delta)

断言某个浮点型数字在X+(-)Y的范围内.

(99.99).should.be.approximately(100, 0.1);


.above(num) and .greaterThan(num)

断言一个数字比某数字大,(>num)

user.age.should.be.above(5);
user.age.should.not.be.above(100);
(5).should.be.above(0);
(5).should.not.be.above(5);


.below(num) and .lessThan(num)

断言一个数字比某数字小(<num)

user.age.should.not.be.below(5);
(5).should.be.below(6);
(5).should.not.be.below(5);

.NaN

//断言某值为nan
(undefined + 0).should.be.NaN;

.Infinity

//断言某值为无穷大
(1/0).should.be.Infinity;

.type(str)

//判断内置类型
user.should.be.type('object');'test'.should.be.type('string');
//附:这个断言一般可以不用,而是用Object.prototype.toString.call(obj).slice(8, -1)判断其内置class,

JavaScript 类型表格(The JavaScript type table)

Value               Class      Type
-------------------------------------
"foo"               String     string
new String("foo")   String     object
1.2                 Number     number
new Number(1.2)     Number     object
true                Boolean    boolean
new Boolean(true)   Boolean    object
new Date()          Date       object
new Error()         Error      object
[1,2,3]             Array      object
new Array(1, 2, 3)  Array      object
new Function("")    Function   function
/abc/g              RegExp     object (function in Nitro/V8)
new RegExp("meow")  RegExp     object (function in Nitro/V8)
{}                  Object     object
new Object()        Object     object
null                Null       object
undefined           Undefined  undefined
NaN                 Number     number
//对于内置类型,使用typeof一般没啥用。判断出来几乎都是Object有毛用。
typeof可以用来typeof xx === undefined判断xx是否为undefined,即xx是否已经被定义;其实xx === undefined也可以。。。
所以可以使用Object.prototype.toString.call(xxx).slice(8, -1)==='typestring'
is('Array',[1, 2]).should.be.ok;//这样判断就ok了

.instanceof(constructor) and .instanceOf(constructor)

断言用户自定义类型(使用instanceof)

user.should.be.an.instanceof(User);
[].should.be.an.instanceOf(Array);

.Object, .Number, .Array, .Boolean, .Function, .String, .Error

//判断内置类型,这些方法比上面的type又更实用一点。还有.NaN,
({}).should.be.an.Object;
(1).should.be.a.Number;
[].should.be.an.Array.and.an.Object;
(true).should.be.a.Boolean;
''.should.be.a.String;


.enumerable(name[, value])

断言是否拥有一个可枚举属性name。value表示其属性的值(使用.eql比较,即==)。

should({name:'lee',age:19}).enumerable('name');
should({name:'lee',age:19}).not.enumerable('toString');


.property(name[, value])

断言是否拥有一个属性,包括继承属性

should({name:'lee',age:19}).property('name');
should({name:'lee',age:19}).property('toString');


注意:.property断言会改变链式结构中的对象,改变为被断言属性的值。这个要小心。


.properties(propName1, propName2, ...) or .properties([propName1, propName2, ...]) or .properties(obj)

断言拥有一系列属性,还可以判断值。

user.should.have.properties('name', 'age');

user.should.have.properties(['name', 'age']);
user.should.have.properties({
    name: 'denis',
    age: 24});

.length(number) and .lengthOf(number)

断言具有length属性,并且等于某值。

user.pets.should.have.length(5);
user.pets.should.have.a.lengthOf(5);
({ length: 10}).should.have.length(10);
//注意length  lengthOf也会改变链式结构的对象


.empty

断言为空,比如String,arrays,argunments的length为0,或者对象没有自己的属性。这个有用

[].should.be.empty;''.should.be.empty;({}).should.be.empty;(function() {

  arguments.should.be.empty;})();


.containEql(otherValue)

断言‘包含’某组成部分,字符串类似contain,数组、对象类似in。


'hello boy'.should.containEql('boy');
[1,2,3].should.containEql(3);
[[1],[2],[3]].should.containEql([3]);
[[1],[2],[3, 4]].should.not.containEql([3]);

({ b: 10 }).should.containEql({ b: 10 });
([1, 2, { a: 10 }]).should.containEql({ a: 10 });
[1, 2, 3].should.not.containEql({ a: 1 });

[{a: 'a'}, {b: 'b', c: 'c'}].should.containEql({a: 'a'});
[{a: 'a'}, {b: 'b', c: 'c'}].should.not.containEql({b: 'b'});


.match(otherValue)

.match非常强大,断言matchs某正则,某自定义函数

 被断言是个字符串:判断匹配给定的正则。

username.should.match(/^\w+$/)

被断言是个数组:判断每个值都匹配给定的正则。

['a', 'b', 'c'].should.not.match(/[d-z]/);

被断言是个对象:判断每个自有属性的值都匹配给定的正则。

({ a: 'foo', c: 'barfoo' }).should.match(/foo$/);
({ a: 'a' }).should.not.match(/^http/);


还可以判断给定的值匹配自定义函数的逻辑。函数内可以在判断逻辑后,返回false、true。也只能返回真假。

(5).should.match(function(n) { return n > 0; });
(5).should.not.match(function(n) { return n < 0; });
(5).should.not.match(function(it) { it.should.be.an.Array; });
(5).should.match(function(it) { return it.should.be.a.Number; });

如果给定的是一个对象,可以分别对其的属性做断言,有点像containDeep,如下:

({ a: 10, b: 'abc', c: { d: 10 }, d: 0 }).should.match({ a: 10, b: /c$/, c: function(it) { return it.should.have.property('d', 10); }});
[10, 'abc', { d: 10 }, 0].should.match({ '0': 10, '1': /c$/, '2': function(it) { return it.should.have.property('d', 10); } });

[10, 'abc', { d: 10 }, 0].should.match([10, /c$/, function(it) { return it.should.have.property('d', 10); }]);


.matchEach(otherValue)

matchEach和match对比,如果被断言的是个值类型,两个方法都一样;

如果是个数组、对象之类的,则match可以对其中每个属性分别做断言,

而matchEach则是对每个属性做一个统一的判断(可以是函数)

另外,对数组、对象这些用match,不能用function对所有属性统一作判断。下面的就出错

[10, 11, 12].should.match(function(it) { return it >= 10; });

所以,一般用matchEach即可,如果要对对象的每个属性分别判断,用containEql,property等即可。

(['a', 'b', 'c']).should.matchEach(/[a-c]/);
[10, 11, 12].should.matchEach(function(it) { return it >= 10; });
[10, 10].should.matchEach(10);

.throw() and throwError()

//断言抛出了错误
(function(){throw new Error('fail');}).should.throw();
//断言没有抛出错误
(function(){}).should.not.throw();
//断言抛出错误的文字内容。这个是根据Error的结构来的。
(function(){throw new Error('fail');}).should.throw('fail');
//断言抛出的错误匹配正则
(function(){throw new Error('failed to foo');}).should.throw(/^fail/);
Error properties to match some other properties (used ):
var error = new Error();
error.a = 10;(function(){ throw error; }).should.throw({ a: 10 });

(function(){ throw error; }).should.throw(Error, { a: 10 });

f
unction isPositive(n) {if(n <= 0) throw new Error('Given number is not positive')}
isPositive.bind(null, 10).should.not.throw();
isPositive.bind(null, -10).should.throw();

要测试异步函数,需要测试该函数是否被执行,还需要在该函数内部测试需要测试的项。结合mocha来比较方便

// first we need to check that function is calledvar called = false;
collection.findOne({ _id: 10 }, function(err, res) {
    called = true;

    //second we test what you want
    res.should.be....});

called.should.be.true;
//结合mocha:
collection.findOne({ _id: 10 }, function(err, res) {
    if(err) return done(err);
    //second we test what you want
    res.should.be....    done();});

Optional Error description可选的错误描述参数

(1).should.eql(0, 'some useful description')
结果:
AssertionError: some useful description
  at Object.eql (/Users/swift/code/should.js/node_modules/should/lib/should.js:280:10)
  ...
如下的断言均具有此参数: eql, equal, within, instanceof, above, below, match, length, property, ownProperty.


转载于:https://my.oschina.net/u/1753171/blog/291817

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值