介绍
chai 是一个断言库,能够与任何 javascript 测试框架完满地配对。反对 BDD 和 TDD 两种格调的断言模式,具备链性能的 BDD 款式提供了一种表白性强的语言和易于浏览的款式,而 TDD 断言款式则提供了更古典的感觉:
- should: BDD 格调断言
- expect: BDD 格调断言
- assert: TDD 格调断言
集体倡议应用expect
,在这里只介绍expect
。
装置
npm install chai
语言链
以下是可链接的获取器,以进步断言的可读性。
- to
- be
- been
- is
- that
- which
- and
- has
- have
- with
- at
- of
- same
- but
- does
- still
.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);
通常最好断言是产生了一个预期的输入,而不是断言没有产生有数意外的输入之一。所以 .not
否定任何断言,并不意味着您应该这样做。
expect(2).to.equal(2); // Recommended
expect(2).to.not.equal(1); // Not recommended
.deep
导致链中前面的所有.equal,.include,.members,.keys 和.property 断言应用深度相等而不是严格 ===
相等。
// Target object deeply (but not strictly) equals `{a: 1}`
expect({a: 1}).to.deep.equal({a: 1});
expect({a: 1}).to.not.equal({a: 1});
// Target array deeply (but not strictly) includes `{a: 1}`
expect([{a: 1}]).to.deep.include({a: 1});
expect([{a: 1}]).to.not.include({a: 1});
// Target object deeply (but not strictly) includes `x: {a: 1}`
expect({x: {a: 1}}).to.deep.include({x: {a: 1}});
expect({x: {a: 1}}).to.not.include({x: {a: 1}});
// Target array deeply (but not strictly) has member `{a: 1}`
expect([{a: 1}]).to.have.deep.members([{a: 1}]);
expect([{a: 1}]).to.not.have.members([{a: 1}]);
// Target set deeply (but not strictly) has key `{a: 1}`
expect(new Set([{a: 1}])).to.have.deep.keys([{a: 1}]);
expect(new Set([{a: 1}])).to.not.have.keys([{a: 1}]);
// Target object deeply (but not strictly) has property `x: {a: 1}`
expect({x: {a: 1}}).to.have.deep.property('x', {a: 1});
expect({x: {a: 1}}).to.not.have.property('x', {a: 1});
.nested
在链中的所有.property 和.include 断言中启用点和括号符号。
expect({a: {b: ['x', 'y']}}).to.have.nested.property('a.b[1]');
expect({a: {b: ['x', 'y']}}).to.nested.include({'a.b[1]': 'y'});
如果 .
或 []
是理论属性名称的一部分,能够通过在其后面增加两个反斜杠来对其进行本义。
expect({'.a': {'[b]': 'x'}}).to.have.nested.property('\\.a.\\[b\\]');
expect({'.a': {'[b]': 'x'}}).to.nested.include({'\\.a.\\[b\\]': 'x'});
.nested 不能与.own 联合应用。
.own
导致链中的所有.property 和.include 断言疏忽继承的属性。
Object.prototype.b = 2;
expect({a: 1}).to.have.own.property('a');
expect({a: 1}).to.have.property('b');
expect({a: 1}).to.not.have.own.property('b');
expect({a: 1}).to.own.include({a: 1});
expect({a: 1}).to.include({b: 2}).but.not.own.include({b: 2});
.own 不能与.nested 组合。
.ordered
使链中前面的所有.member 断言要求成员的程序雷同。
expect([1, 2]).to.have.ordered.members([1, 2]).but.not.have.ordered.members([2, 1]);
当.include 和.ordered 组合在一起时,排序从两个数组的结尾开始。
expect([1, 2, 3]).to.include.ordered.members([1, 2])
.but.not.include.ordered.members([2, 3]);
.any
使链中的所有.keys 断言仅要求指标具备至多一个给定的键。
这与.all 相同,后者要求指标具备所有给定的键。
expect({a: 1, b: 2}).to.not.have.any.keys('c', 'd');
无关何时应用.any 或.all 的指南,请参见.keys 文档。
.all
导致链中前面的所有.keys 断言要求指标具备所有给定的键。
这与.any 相同,后者仅要求指标具备至多一个给定的键。
expect({a: 1, b: 2}).to.have.all.keys('a', 'b');
请留神,当.all 和.any 都未在链中的晚期增加时,默认状况下将应用.all。
然而,通常最好还是增加.all,因为它能够进步可读性.
无关何时应用.any 或.all 的指南,请参见.keys 文档。
.a(type[, msg])
- @param {String} type
- @param {String} msg optional
断言指标的类型等于给定的字符串类型。
类型不辨别大小写。
无关类型检测算法的信息.
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');
.a
反对通过 Symbol.toStringTag 设置了自定义类型的对象。
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;
在链的后面增加.not,以取反 .a
。
然而,通常最好断言指标是预期的类型,而不是断言它不是许多意外类型之一。
expect('foo').to.be.a('string'); // Recommended
expect('foo').to.not.be.an('array'); // Not recommended
.a
承受一个可选的 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
调换应用。
.include(val[, msg])
- @param {Mixed} val
- @param {String} msg optional
当指标是字符串时,.include 断言给定的字符串 val 是指标的子字符串。
expect('foobar').to.include('foo');
当指标是数组时,.include 断言给定的 val 是指标的成员。
expect([1, 2, 3]).to.include(2);
当指标是对象时,.include 断言给定对象 val 的属性是指标属性的子集。
expect({a: 1, b: 2, c: 3}).to.include({a: 1, b: 2});
当指标是 Set 或 WeakSet 时,.include 断言给定 val 是指标的成员。应用 SameValueZero 相等算法。
expect(new Set([1, 2])).to.include(2);
当指标是 Map 时,.include 断言给定的 val 是指标的值之一。应用 SameValueZero 相等算法。
expect(new Map([['a', 1], ['b', 2]])).to.include(2);
因为.include 会依据指标的类型执行不同的操作,因而在应用.include 之前查看指标的类型很重要。无关测试指标类型的信息,请参阅.a 文档。
expect([1, 2, 3]).to.be.an('array').that.includes(2);
默认状况下,应用严格(===)相等性比拟数组成员和对象属性。
在链的后面增加.deep,以改为应用深度相等(不反对 WeakSet 指标)。
// Target array deeply (but not strictly) includes `{a: 1}`
expect([{a: 1}]).to.deep.include({a: 1});
expect([{a: 1}]).to.not.include({a: 1});
// Target object deeply (but not strictly) includes `x: {a: 1}`
expect({x: {a: 1}}).to.deep.include({x: {a: 1}});
expect({x: {a: 1}}).to.not.include({x: {a: 1}});
默认状况下,应用对象时会搜寻指标的所有属性。这包含继承和 / 或不可枚举的属性。在链的后面增加.own 能够从搜寻中排除指标的继承属性。
Object.prototype.b = 2;
expect({a: 1}).to.own.include({a: 1});
expect({a: 1}).to.include({b: 2}).but.not.own.include({b: 2});
请留神,始终仅在指标对象中搜寻 val 本人的可枚举属性。
.deep 和.own 能够组合应用。
expect({a: {b: 2}}).to.deep.own.include({a: {b: 2}});
在援用嵌套属性时,在链的后面增加.nested 以启用点和括号符号。
expect({a: {b: ['x', 'y']}}).to.nested.include({'a.b[1]': 'y'});
如果 .
或 []
是理论属性名称的一部分,能够通过在其后面增加两个反斜杠来对其进行本义。
expect({'.a': {'[b]': 2}}).to.nested.include({'\\.a.\\[b\\]': 2});
.deep 和.nested 能够组合应用。
expect({a: {b: [{c: 3}]}}).to.deep.nested.include({'a.b[0]': {c: 3}});
.own 和.nested 不能合并。
在链的后面增加.not,以对消.include。
expect('foobar').to.not.include('taco');
expect([1, 2, 3]).to.not.include(4);
然而,当指标是对象时,否定.include 是很危险的。问题在于,它断言指标对象没有 val 的所有键 / 值对,但可能有也可能没有,因而产生了不确定的冀望。通常最好先确定冀望的确切输入,而后编写仅承受该准确输入的断言。
当甚至不心愿指标对象具备 val 键时,通常最好精确地断言。
expect({c: 3}).to.not.have.any.keys('a', 'b'); // Recommended
expect({c: 3}).to.not.include({a: 1, b: 2}); // Not recommended
当冀望指标对象具备 val 的键时,通常最好断言每个属性都有其期望值,而不是断言每个属性都没有许多意外值之一。
expect({a: 3, b: 4}).to.include({a: 3, b: 4}); // Recommended
expect({a: 3, b: 4}).to.not.include({a: 1, b: 2}); // Not recommended
.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 断言要求指标是预期汇合的超集,而不是同一汇合。请留神,增加.include 时,.members 会疏忽子集中的反复项。
// 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]);
请留神,在链中的后面增加.any 会导致.keys 断言疏忽.include。
// Both assertions are identical
expect({a: 1}).to.include.any.keys('a', 'b');
expect({a: 1}).to.have.any.keys('a', 'b');
别名.includes,.contain 和.contains 能够与.include 调换应用。
.ok
断言指标是实在值(在布尔上下文中认为是实在)。
然而,通常最好断言该指标严格(===)或深等于其预期值。
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
在链的后面增加.not 即可勾销.ok。
expect(0).to.equal(0); // Recommended
expect(0).to.not.be.ok; // Not recommended
expect(false).to.be.false; // Recommended
expect(false).to.not.be.ok; // Not recommended
expect(null).to.be.null; // Recommended
expect(null).to.not.be.ok; // Not recommended
expect(undefined).to.be.undefined; // Recommended
expect(undefined).to.not.be.ok; // Not recommended
能够将自定义谬误音讯作为预期的第二个参数。
expect(false, 'nooo why fail??').to.be.ok;
.true
断言指标严格(===)等于 true。
expect(true).to.be.true;
在链的后面增加.not 即可勾销.true。然而,通常最好断言指标等于其期望值,而不是不等于实在值。
expect(false).to.be.false; // Recommended
expect(false).to.not.be.true; // Not recommended
expect(1).to.equal(1); // Recommended
expect(1).to.not.be.true; // Not recommended
能够将自定义谬误音讯作为预期的第二个参数。
expect(false, 'nooo why fail??').to.be.true;
.false
断言指标严格(===)等于 false。
expect(null).to.be.false;
.null
断言指标严格(===)等于 null。
expect(null).to.be.null;
.undefined
断言指标严格(===)等于 undefined。
expect(undefined).to.be.undefined;
.NaN
断言指标严格(===)等于 NaN。
expect(NaN).to.be.NaN;
.exist
断言指标不严格等于(===)null 或未定义。然而,通常最好断言指标等于其期望值。
expect(1).to.equal(1); // Recommended
expect(1).to.exist; // Not recommended
expect(0).to.equal(0); // Recommended
expect(0).to.exist; // Not recommended
.empty
当指标是字符串或数组时,.empty 断言指标的 length 属性严格(===)等于 0。
expect([]).to.be.empty;
expect('').to.be.empty;
当指标是地图或汇合时,.empty 断言指标的 size 属性严格等于 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;
在链的后面增加.not 即可勾销.empty。然而,通常最好断言指标蕴含其预期的值数,而不是断言目标值不为空。
expect([1, 2, 3]).to.have.lengthOf(3); // Recommended
expect([1, 2, 3]).to.not.be.empty; // Not recommended
expect(new Set([1, 2, 3])).to.have.property('size', 3); // Recommended
expect(new Set([1, 2, 3])).to.not.be.empty; // Not recommended
expect(Object.keys({a: 1})).to.have.lengthOf(1); // Recommended
expect({a: 1}).to.not.be.empty; // Not recommended