chai学习笔记

Chai是具有BDD/TDD风格的验证库,可以运行在node和浏览器环境中,一般和各类JavaScript框架一起使用。本文主要介绍在node环境中的使用。

为什么说Chai同时具有BDD或者TDD风格呢?因为Chai提供了不同风格的接口

  • shouldexpect接口提供了BDD链式风格,是一种更加易读的风格
    • tea.should.have.property('flavors').with.lengthOf(3);
    • expect(tea).to.have.property('flavors').with.lengthOf(3)
  • assert提供了更加经典的TDD验证风格
    • assert.lengthOf(tea.flavors, 3);

安装

安装可以使用npm install chai。更加推荐的做法是在package.json里面添加chai,然后使用npm install去安装。

"devDependencies": {
  "chai": "*"
}

使用*可以让每一次执行npm install的时候都去下载安装Chai的最新版本,这在持续集成里面能发挥很大的作用。

chai.expect

让我们通过常用方法的实例来看下如何使用chai.expect

Chains Getter

下面所有的chains都可以用来增加验证表达式的可读性,读起来更接近自然语言。

  • to
  • be
  • been
  • is
  • that
  • which
  • and
  • has
  • have
  • with
  • at
  • of
  • same
  • but
  • does

.equal

.equal应该算是验证里面用得最多的方法了,用来验证两个对象是否相等,本质是用了strictly equal (===)。.equal(val[,msg])接受两个参数,第一个是期望值,第二个值是可选的当验证失败时会返回的错误消息。也可以使用.eq

典型用法

expect(1).to.equal(1);
expect('foo').to.equal('foo');
expect(1).to.equal(2, 'this is error msg');
expect('foo').to.eq('foo');

.equal.deep一起使用的时候,使用的是deep-eql而不是strictly equal (===)

expect({a: 1}).to.equal({a: 1}); // fail
expect({a: 1}).to.deep.equal({a: 1}); //pass

.eql

.eql(obj[, msg])验证目标对象与给出的参数objdeeply equal。效果和.equal.deep一起使用一样,不过.deep.equal对chain的影响更大

// Target object is deeply (but not strictly) equal to {a: 1}
expect({a: 1}).to.eql({a: 1}).but.not.equal({a: 1});

// Target array is deeply (but not strictly) equal to [1, 2]
expect([1, 2]).to.eql([1, 2]).but.not.equal([1, 2]);

.eql的自定义错误消息可以通过expect的第二个参数和.eql的第二个参数实现

expect({a: 1}).to.eql({b: 2}, 'nooo why fail??');
expect({a: 1}, 'nooo why fail??').to.eql({b: 2});

.eqls.eql作用相同,可交换使用。

.property

.property(name[,val[,msg]])用来判断对象里面的key是否存在,以及在提供第二个参数val的情况下验证该key对应的value值

expect({a: 1}).to.have.property('a');
expect({a: 1}).to.have.property('a', 1);

.property.deep一起使用的时候,使用的是deep-eql而不是strictly equal (===)

expect({x: {a: 1}}).to.have.deep.property('x', {a: 1}); //pass
expect({x: {a: 1}}).to.have.property('x', {a: 1}); //fail

.property可以与.own一起使用来排除继承的属性

Object.prototype.b = 2;

expect({a: 1}).to.have.own.property('a');
expect({a: 1}).to.have.own.property('a', 1);
expect({a: 1}).to.have.property('b').but.not.own.property('b');

.property可以与.nested一起使用来验证多层内嵌属性

expect({a: {b: ['x', 'y']}}).to.have.nested.property('a.b[1]');
expect({a: {b: ['x', 'y']}}).to.have.nested.property('a.b[1]', 'y');

.deep & .own & .nested可以一起使用

expect({x: {a: 1}}).to.have.deep.own.property('x', {a: 1});
expect({a: {b: [{c: 3}]}}).to.have.deep.nested.property('a.b[0]', {c: 3});

.include

.include(val[,msg])用来验证某种对象子集的包含关系

当对象是字符串的时候,用来判断参数val是否是目标字符串的子集 expect('foobar').to.include('foo');

当对象是数组的时候,用来判断参数val是否是数组的一员 expect([1, 2, 3]).to.include(2);

当对象是字典的时候,用来判断参数val是否是目标对象的子集 expect({a: 1, b: 2, c: 3}).to.include({a: 1, b: 2});

当对象是集合的时候,用来判断参数val是否是集合的一员 expect([1, 2, 3]).to.include(2);

当对象是Map的时候,用来判断参数val是某一对象的值 expect(new Map([['a', 1], ['b', 2]])).to.include(2);

一般来讲,因为.include会根据目标对象类型的不同而表现出不同的行为,我们通常在使用.include之前都会检查对象类型 expect([1, 2, 3]).to.be.an('array').that.includes(2);

默认情况下,strict (===) equality用来比较数组元素和对象属性,如果在链式结构里面加上.deep,使用的是deep-eql

expect([{a: 1}]).to.include({a: 1}); \\fail
expect([{a: 1}]).to.deep.include({a: 1}); \\pass
expect({x: {a: 1}}).to.include({x: {a: 1}}); \\fail
expect({x: {a: 1}}).to.deep.include({x: {a: 1}}) \\pass

.include可以与.own一起使用来排除继承的属性

Object.prototype.b = 2;

expect({a: 1}).to.own.include({a: 1});
expect({a: 1}).to.include({a: 1}).but.not.own.include({b: 2});

.deep.own可以一起使用 expect({a: {b: 2}}).to.deep.own.include({a: {b: 2}});

.include可以与.nested一起使用来验证多层内嵌属性 expect({a: {b: ['x', 'y']}}).to.nested.include({'a.b[1]': 'y'});

.deep.nested可以一起使用 expect({a: {b: [{c:3}]}}).to.deep.nested.include({'a.b[0]': {c: 3}});

如果.[]是真实的属性名称,可以通过双反斜杠来进行转义expect({'.a': {'[b]': 2}}).to.nested.include({'\\.a.\\[b\\]': 2});

当目标对象是去验证参数val的key的时候,通常我们最好带上value一起做验证expect({a: 3, b: 4}).to.include({a: 3, b: 4});

.include的第二个可选参数msg是当验证失败时会显示的定制错误消息

expect([1, 2, 3]).to.include(4, 'nooo why fail??');
expect([1, 2, 3], 'nooo why fail??').to.include(4);

.include用作链式属性且与.members.keys一起使用时,会去验证目标是不是目标对象的子集。

// Target object's keys are a superset of ['a', 'b'] but not identical
expect({a: 1, b: 2, c: 3}).to.include.all.keys('a', 'b');
expect({a: 1, b: 2, c: 3}).to.not.have.all.keys('a', 'b');

// Target array is a superset of [1, 2] but not identical
expect([1, 2, 3]).to.include.members([1, 2]);
expect([1, 2, 3]).to.not.have.members([1, 2]);

// Duplicates in the subset are ignored
expect([1, 2, 3]).to.include.members([1, 2, 2, 2]);

.members

.members(set[,msg])用来验证目标数组是不是和参数set数组的成员完全一致。

expect([1, 2, 3]).to.have.members([2, 1, 3]);
expect([1, 2, 2]).to.have.members([2, 1, 2]);

由上可知,.members是完全匹配且忽略数组元素的顺序。

默认情况下,strict (===) equality用来比较数组成员,如果在链式结构里面加上.deep,使用的是deep-eql

expect([{a: 1}]).to.have.deep.members([{a: 1}]); //pass
expect([{a: 1}]).to.have.members([{a: 1}]); //fail

如果成员的顺序也是验证点,那需要用上.ordered

expect([1, 2, 3]).to.have.ordered.members([2, 1, 3]); //fail
expect([1, 2, 3]).to.have.ordered.members([1, 2, 3]); //pass
expect([1, 2, 3]).to.have.members([2, 1, 3]).but.not.ordered.members([2, 1, 3]); //pass

默认情况下.members会去验证数组的长度是一致的。加上.include会去验证目标是不是目标对象的子集而不要求数组长度一致。

// Target array is a superset of [1, 2] but not identical
expect([1, 2, 3]).to.include.members([1, 2]);
expect([1, 2, 3]).to.not.have.members([1, 2]);

// Duplicates in the subset are ignored
expect([1, 2, 3]).to.include.members([1, 2, 2, 2]);

.deep & .include & ordered可以和.members一起使用。

expect([{a: 1}, {b: 2}, {c: 3}]).to.include.deep.ordered.members([{a: 1}, {b: 2}]); //pass
expect([{a: 1}, {b: 2}, {c: 3}]).to.include.deep.ordered.members([{b: 2}, {c: 3}]); //fail

第二个参数msg是自定义的错误消息,在验证出错时输出。

expect([1, 2]).to.have.members([1, 2, 3], 'nooo why fail??');
expect([1, 2], 'nooo why fail??').to.have.members([1, 2, 3]);

.a

.a(type[, msg])用于验证目标对象与给出的对象的类型是否一致。关于目标对象类型也是就是参数type,实际上是全小写的字符串。更多信息请参考这里

来看几个列子

expect('foo').to.be.a('string');
expect({a: 1}).to.be.an('object');
expect(null).to.be.a('null');
expect(undefined).to.be.an('undefined');
expect(new Error).to.be.an('error');
expect(Promise.resolve()).to.be.a('promise');
expect(new Float32Array).to.be.a('float32array');
expect(Symbol()).to.be.a('symbol');

通过Symbol.toStringTag自定义的类型能够被.a支持。

var myObj = {
  [Symbol.toStringTag]: 'myCustomType'
};

expect(myObj).to.be.a('myCustomType').but.not.an('object');

.a的通常用在验证前检测目标对象的类型,这样可以避免那些根据目标类型不同而展示出不同行为的方法的不正常使用

expect([1, 2, 3]).to.be.an('array').that.includes(2);
expect([]).to.be.an('array').that.is.empty;

第二个参数msg是自定义的错误消息,在验证出错时输出。

expect(1).to.be.a('string', 'nooo why fail??');
expect(1, 'nooo why fail??').to.be.a('string');

.a除了验证数据类型之外,在链式结构中也可以增强阅读性。
expect({b: 2}).to.have.a.property('b');

.an.a作用相同,可交换使用。

.keys

.keys(key1[, key2[, …]])用于某一个key是否存在于目标对象(object, array, map, set)中。

当目标对象是字典或是数组的时候,参数key可以是

  • 一个或多个字符串参数
  • 一个数组
  • 一个对象
expect({a: 1, b: 2}).to.have.all.keys('a', 'b');
expect(['x', 'y']).to.have.all.keys(0, 1);

expect({a: 1, b: 2}).to.have.all.keys(['a', 'b']);
expect(['x', 'y']).to.have.all.keys([0, 1]);

expect({a: 1, b: 2}).to.have.all.keys({a: 4, b: 5}); // ignore 4 and 5
expect(['x', 'y']).to.have.all.keys({0: 4, 1: 5}); // ignore 4 and 5

当目标对象是map或set的时候,只能是分隔的参数

expect(new Map([['a', 1], ['b', 2]])).to.have.all.keys('a', 'b');
expect(new Set(['a', 'b'])).to.have.all.keys('a', 'b');

由上所知,.keys根据目标对象的不同而有不同的处理,所以.a可以用在.keys之前来检测目标对象的数据类型。expect({a: 1, b: 2}).to.be.an('object').that.has.all.keys('a', 'b');

默认情况下,strict (===) equality用来比较数组成员,如果在链式结构里面加上.deep,使用的是deep-eql

expect(new Set([{a: 1}])).to.have.all.deep.keys([{a: 1}]); //pass
expect(new Set([{a: 1}])).to.have.all.keys([{a: 1}]); //fail

当给keys加上了.not,通常会使用any来搭配。.not.any.keys可以验证到给出的key每一个都不在目标对象中,然而not.any.all做不到。

比如测试目的是验证c和d都不在目标对象中,然后expect({a: 1, b: 2, c: 3}).to.not.have.all.keys('c', 'd');能通过因为目标对象并没有have all keys也就是c,d同时存在,在取反就会返回true。使用expect({a: 1, b: 2}).to.not.have.any.keys('c', 'd');可以达到目的,能够验证目标对象没有任意其中一个key。

如果在.keys之前加上.any就会抵消.include的作用

// Both assertions are identical
expect({a: 1}).to.include.any.keys('a', 'b');
expect({a: 1}).to.have.any.keys('a', 'b');

自定义的错误消息以expect第二个参数给出。expect({a: 1}, 'nooo why fail??').to.have.key('b');

.key.keys作用相同,可交换使用。

.any

.any使得所有.keys验证只要求目标对象包含至少一个指定的keys。与.all的作用相反。expect({a: 1, b: 2}).to.have.any.keys('a', 'd');

.all

.all使得所有.keys验证只要求目标对象包含所有指定的keys。与.any的作用相反。expect({a: 1, b: 2}).to.have.all.keys('a', 'b');

这是.keys默认地匹配方式,可以不显示地加上,但是一般加上的话易读性会更好。

.not

.not可以会进行否定式验证。

expect(function () {}).to.not.throw();
expect({a: 1}).to.not.have.property('b');
expect([1, 2]).to.be.an('array').that.does.not.include(3);

不过这种方法不是特别推荐,验证应该直指具体特定的单一目标行为而不是否定式验证,因为否定式验证只是验证多个无效行为中的一个,并不能保证正确性。

expect(2).to.equal(2);
expect(2).to.not.equal(1);

很明显,上面第二种方式不是好的验证方式

.throw

.throw([errorLike], [errMsgMatcher], [msg])用来验证方法是否抛出期待的异常错误。

当没有参数的时候,.throw会触发目标方法而验证错误已经抛出

var badFn = function () { throw new TypeError('Illegal salmon!'); };

expect(badFn).to.throw();

当参数被提供并且是错误构造函数,.throw会触发目标方法而验证错误已经抛出一个错误实例

var badFn = function () { throw new TypeError('Illegal salmon!'); };

expect(badFn).to.throw(TypeError);

当参数被提供并且是错误实例,.throw会触发目标方法而且验证被抛出的错误实例strictly equality(===)提供的错误实例

var err = new TypeError('Illegal salmon!');
var badFn = function () { throw err; };

expect(badFn).to.throw(err);

当参数被提供并且是字符串,.throw会触发目标方法而且验证被抛出的错误消息中包含提供字符串参数

var badFn = function () { throw new TypeError('Illegal salmon!'); };

expect(badFn).to.throw('salmon');

当参数被提供并且是正则表达式,.throw会触发目标方法而且验证被抛出的错误消息中匹配提供的正则表达式。

var badFn = function () { throw new TypeError('Illegal salmon!'); };

expect(badFn).to.throw(/salmon/);

当两个参数被提供,第一个是错误实例或构造函数,第二个是正则表达式或是字符串;.throw会触发目标方法,然后像上面描述的那样组合起来工作

var err = new TypeError('Illegal salmon!');
var badFn = function () { throw err; };

expect(badFn).to.throw(TypeError, 'salmon');
expect(badFn).to.throw(TypeError, /salmon/);
expect(badFn).to.throw(err, 'salmon');
expect(badFn).to.throw(err, /salmon/);

.ok

.ok用来验证目标对象loosely(==) equal与true相等。通常还是推荐使用strictly(===) equal来进行判断

expect(1).to.equal(1); // Recommended
expect(1).to.be.ok; // Not recommended

expect(true).to.be.true; // Recommended
expect(true).to.be.ok; // Not recommended

expect的第二个参数可以提供自定义的错误消息。expect(false, 'nooo why fail??').to.be.ok;

.true

.true用来验证目标对象strictly(===) equal与true相等
expect(true).to.be.true;

expect的第二个参数可以提供自定义的错误消息。expect(false, 'nooo why fail??').to.be.true;

.false

.false用来验证目标对象strictly(===) equal与false相等
expect(false).to.be.false;

expect的第二个参数可以提供自定义的错误消息。expect(true, 'nooo why fail??').to.be.false;

.null

.null用来验证目标对象strictly(===) equal与null相等
expect(null).to.be.null;

expect的第二个参数可以提供自定义的错误消息。expect(11, 'nooo why fail??').to.be.null;

.undefined

.undefined用来验证目标对象strictly(===) equal与undefined相等
expect(undefined).to.be.undefined;

expect的第二个参数可以提供自定义的错误消息。expect(11, 'nooo why fail??').to.be.null;

.NaN

.NaN用来验证目标对象strictly(===) equal与NaN相等
expect(NaN).to.be.NaN;

expect的第二个参数可以提供自定义的错误消息。expect(11, 'nooo why fail??').to.be.NaN;

.exist

.exist用来验证目标对象不等于strictly (===) equal null或是undefined来证明目标对象是存在。然后一般会推荐验证目标对象为某一个特定的值。

expect(1).to.equal(1); // Recommended
expect(1).to.exist; // Not recommended

expect(0).to.equal(0); // Recommended
expect(0).to.exist; // Not recommended

expect的第二个参数可以提供自定义的错误消息。expect(null, 'nooo why fail??').to.exist;

.empty

当目标对象是字符串或是数组的时候,.empty验证其长度(length属性)是否等于(strictly equal ===)0。

expect([]).to.be.empty;
expect('').to.be.empty;

当目标对象是set或map的时候,.empty验证其大小(size属性)是否等于(strictly equal ===)0。

expect(new Set()).to.be.empty;
expect(new Map()).to.be.empty;

当目标对象是非方法的对象,.empty验证对象没有任何可枚举的属性。expect({}).to.be.empty;

因为.empty根据目标对象不同而表现出不同的行为,所以可以在使用.empty之前使用.a来检测目标对象类型。expect([]).to.be.an('array').that.is.empty;

expect的第二个参数可以提供自定义的错误消息。expect([1, 2, 3], 'nooo why fail??').to.be.empty;

.arguments

.arguments验证目标对象是一个arguments对象。

function test () {
  expect(arguments).to.be.arguments;
}

test();

expect的第二个参数可以提供自定义的错误消息。expect({}, 'nooo why fail??').to.be.arguments;

.Arguments.arguments作用相同,可交换使用。

.above

.above(n[, msg])验证目标对象大于给定的数值或日期。expect(2).to.equal(2);

.gt, .greaterThan.above作用相同,可交换使用。

.least

.least(n[, msg])验证目标对象至少是(大于或等于)给定的数值或日期 expect(2).to.be.at.least(1);, expect(2).to.be.at.least(2);

.below

.below(n[, msg])验证目标对象小于给定的数值或日期。expect(1).to.be.below(2);
.lt, .lessThan.below作用相同,可交换使用。

.most

.most(n[, msg])验证目标对象最多是(小于或等于)给定的数值或日期 expect(1).to.be.at.most(2);, expect(1).to.be.at.least(1);

.within

.within(start, finish[, msg])验证目标是某一个闭区间内,也就是大于或等于start参数,小于或等于finish参数。

expect(2).to.be.within(1, 3);
expect(2).to.be.within(2, 3);
expect(2).to.be.within(1, 2);

.instanceof

.instanceof(constructor[, msg])验证目标函数是给定构造函数的实例。

function Cat () { }

expect(new Cat()).to.be.an.instanceof(Cat);
expect([1, 2]).to.be.an.instanceof(Array);

.lengthOf

.lengthOf(n[, msg])验证目标对象的length属性是否等于给定的数值。

expect([1, 2, 3]).to.have.lengthOf(3);
expect('foo').to.have.lengthOf(3);

.lengthOf也可以用于语句链式结构中,和.above, .below, .least, .most.within一起使用时,会让这些方法去验证目标对象的length属性。不过,并不推荐这种写法,因为我们应该直接验证期待的具体数值而不是范围。

// Recommended
expect([1, 2, 3]).to.have.lengthOf(3);

// Not recommended
expect([1, 2, 3]).to.have.lengthOf.above(2);
expect([1, 2, 3]).to.have.lengthOf.below(4);
expect([1, 2, 3]).to.have.lengthOf.at.least(3);
expect([1, 2, 3]).to.have.lengthOf.at.most(3);
expect([1, 2, 3]).to.have.lengthOf.within(2,4);

.match

.match(re[, msg])验证目标函数匹配给定的正则表达式。expect('foobar').to.match(/^foo/);

.string

.string(str[, msg])验证目标函数包含给定的子字符串strexpect('foobar').to.have.string('bar');

.respondTo

当目标对象不是函数时,.respondTo(method[, msg])验证目标对象包含一个给定的函数,这个函数的名字就是参数method.下面的例子表明了Cat实例中包含了一个函数叫做meow。这个函数可以是继承的。

function Cat () {}
Cat.prototype.meow = function () {};

expect(new Cat()).to.respondTo('meow');

当目标对象是函数的时候,.respondTo验证目标函数的prototype属性包含一个名称为参数method的函数。这个函数可以是继承的。

function Cat () {}
Cat.prototype.meow = function () {};

expect(Cat).to.respondTo('meow');

在链接结构中加入.itself会使得.respondTo把目标对象不当成函数来处理,所以是去验证目标对象有一个给定名称的函数而不是去验证目标函数的prototype属性包含一个名称为参数method的函数,即使传入的目标对象是函数本身。下面例子表明加入.itself之后,在prototype属性加上的函数meow就不会被验证到。

function Cat () {}
Cat.prototype.meow = function () {};
Cat.hiss = function () {};

expect(Cat).itself.to.respondTo('hiss').but.not.respondTo('meow');

在验证方法是否存在之前,我们也可以先验证下目标对象的类型。

function Cat () {}
Cat.prototype.meow = function () {};

expect(new Cat()).to.be.an('object').that.respondsTo('meow');

加上.not进行negative的判断

function Dog () {}
Dog.prototype.bark = function () {};

expect(new Dog()).to.not.respondTo('meow');

.respondTo接受第二个可选参数msg来自定义错误消息,也可以加上第二个参数给expect()

expect({}).to.respondTo('meow', 'nooo why fail??');
expect({}, 'nooo why fail??').to.respondTo('meow');

.satisfy

.satisfy(matcher[, msg])的参数matcher是一个方法,这个方法会接受目标对象当做第一个参数,并且进行验证且返回true。

下面这个例子中1作为目标对象传给了matcher方法,进行了判断,返回了true

expect(1).to.satisfy(function(num) {
  return num > 0;
});

.satisfy接受第二个可选参数msg来自定义错误消息,也可以加上第二个参数给expect()

expect(1).to.satisfy(function(num) {
  return num > 2;
}, 'nooo why fail??');

expect(1, 'nooo why fail??').to.satisfy(function(num) {
  return num > 2;
});

.satisfies.satisfy作用相同,可以交换使用。

.closeTo

.closeTo(expected, delta[, msg])验证目标对象与参数expected的正负差距在参数delta之内。不过不是很推荐这种不精准的验证。

// Recommended
expect(1.5).to.equal(1.5);

// Not recommended
expect(1.5).to.be.closeTo(1, 0.5);
expect(1.5).to.be.closeTo(2, 0.5);
expect(1.5).to.be.closeTo(1, 1);

.closeTo接受第三个可选参数msg来自定义错误消息,也可以加上第二个参数给expect()

expect(1.5).to.be.closeTo(3, 1, 'nooo why fail??');
expect(1.5, 'nooo why fail??').to.be.closeTo(3, 1);

.approximately.closeTo作用相同,可以交换使用。

.oneOf

.oneOf(list[, msg])验证目标对象是参数数组list的一员。

expect(1).to.equal(1); // Recommended
expect(1).to.be.oneOf([1, 2, 3]); // Not recommended

.oneOf接受第三个可选参数msg来自定义错误消息,也可以加上第二个参数给expect()

expect(1).to.be.oneOf([2, 3, 4], 'nooo why fail??');
expect(1, 'nooo why fail??').to.be.oneOf([2, 3, 4]);

.increase

当一个参数subject被给出的时候,.increase(subject[, prop[, msg]])验证参数方法subject返回的值比目标函数返回的数值大。目标函数会先于参数函数调用。使用.by可以验证具体数值。

var val = 1
  , addTwo = function () { val += 2; }
  , getVal = function () { return val; };

expect(addTwo).to.increase(getVal).by(2); // Recommended
expect(addTwo).to.increase(getVal); // Not recommended

当两个参数subjectprop被给出的时候,.increase(subject[, prop[, msg]])验证目标对象subjectprop属性值比目标函数返回的数值大。

var myObj = {val: 1}
  , addTwo = function () { myObj.val += 2; };

expect(addTwo).to.increase(myObj, 'val').by(2); // Recommended
expect(addTwo).to.increase(myObj, 'val'); // Not recommended

.increase接受第三个可选参数msg来自定义错误消息,也可以加上第二个参数给expect()

var myObj = {val: 1}
  , noop = function () {};

expect(noop).to.increase(myObj, 'val', 'nooo why fail??');

var val = 1
  , noop = function () {}
  , getVal = function () { return val; };

expect(noop, 'nooo why fail??').to.increase(getVal);

.increases.increase作用相同,可以交换使用。

.decrease(subject[, prop[, msg]])作用与.increase恰好相反。

.extensible

.extensible验证目标对象可以加入新的属性。expect({a: 1}).to.be.extensible;

.sealed

.sealed验证目标对象是sealed Object,意思就是不能加入新的属性,已经存在的属性不能被删除或reconfigured,但是已经存在的属性可以被assign新的值。

var sealedObject = Object.seal({});
var frozenObject = Object.freeze({});

expect(sealedObject).to.be.sealed;
expect(frozenObject).to.be.sealed;
expect(1).to.be.sealed;

.frozen

.frozen验证目标对象被frozen Object,意思就是不能加入新的属性,已经存在的属性不能被删除或reconfigured或被assign新的值。

var frozenObject = Object.freeze({});

expect(frozenObject).to.be.frozen;
expect(1).to.be.frozen;

.finite

.finite验证目标对象是一个数值并且不是NaNInfinityexpect().to.be.finite

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

推荐阅读更多精彩内容