BDD

BDD 风格有 expectshould。两者都使用相同的链式语言来构建断言,但它们在断言的初始构建方式上有所不同。查看 风格指南 以进行比较。

API 参考

语言链

以下提供为可链式获取器,以提高断言的可读性。

  • 已经
  • 相同
  • 仍然

.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 断言使用深度相等性而不是严格 (===) 相等性。有关深度相等性算法的信息,请参阅 deep-eql 项目页面:https://github.com/chaijs/deep-eql。

// 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

导致链中所有后续的 .members 断言要求成员按相同顺序排列。

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 _可选_

断言目标的类型等于给定的字符串 type。类型不区分大小写。有关类型检测算法的信息,请参阅 type-detect 项目页面:https://github.com/chaijs/type-detect。

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 的第二个参数提供。

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 _可选_

当目标是字符串时,.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 目标)。有关深度相等性算法的信息,请参阅 deep-eql 项目页面:https://github.com/chaijs/deep-eql。

// 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 的第二个参数给出。

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

断言目标是真值(在布尔上下文中被认为是 true)。但是,通常最好断言目标严格地 (===) 或深度地等于其预期值。

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 的第二个参数给出。

expect(false, 'nooo why fail??').to.be.ok;

.true

断言目标严格地 (===) 等于 true

expect(true).to.be.true;

在链中更早地添加 .not 来否定 .true。但是,通常最好断言目标等于其预期值,而不是不等于 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 的第二个参数给出。

expect(false, 'nooo why fail??').to.be.true;

.false

断言目标严格地 (===) 等于 false

expect(false).to.be.false;

在链中更早地添加 .not 来否定 .false。但是,通常最好断言目标等于其预期值,而不是不等于 false

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

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

可以将自定义错误消息作为 expect 的第二个参数给出。

expect(true, 'nooo why fail??').to.be.false;

.null

断言目标严格地 (===) 等于 null

expect(null).to.be.null;

在链中更早地添加 .not 来否定 .null。但是,通常最好断言目标等于其预期值,而不是不等于 null

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

可以将自定义错误消息作为 expect 的第二个参数给出。

expect(42, 'nooo why fail??').to.be.null;

.undefined

断言目标严格地 (===) 等于 undefined

expect(undefined).to.be.undefined;

在链中更早地添加 .not 来否定 .undefined。但是,通常最好断言目标等于其预期值,而不是不等于 undefined

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

可以将自定义错误消息作为 expect 的第二个参数给出。

expect(42, 'nooo why fail??').to.be.undefined;

.NaN

断言目标完全是 NaN

expect(NaN).to.be.NaN;

在链中更早地添加 .not 来否定 .NaN。但是,通常最好断言目标等于其预期值,而不是不等于 NaN

expect('foo').to.equal('foo'); // Recommended
expect('foo').to.not.be.NaN; // Not recommended

可以将自定义错误消息作为 expect 的第二个参数给出。

expect(42, 'nooo why fail??').to.be.NaN;

.exist

断言目标不严格地 (===) 等于 nullundefined。但是,通常最好断言目标等于其预期值。

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

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

在链中更早地添加 .not 来否定 .exist

expect(null).to.be.null; // Recommended
expect(null).to.not.exist; // Not recommended

expect(undefined).to.be.undefined; // Recommended
expect(undefined).to.not.exist; // Not recommended

可以将自定义错误消息作为 expect 的第二个参数给出。

expect(null, 'nooo why fail??').to.exist;

别名 .exists 可以与 .exist 交换使用。

.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

可以将自定义错误消息作为 expect 的第二个参数给出。

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

.arguments

断言目标是 arguments 对象。

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

test();

在链中更早地添加 .not 来否定 .arguments。但是,通常最好断言目标的预期类型,而不是断言它不是 arguments 对象。

expect('foo').to.be.a('string'); // Recommended
expect('foo').to.not.be.arguments; // Not recommended

可以将自定义错误消息作为 expect 的第二个参数给出。

expect({}, 'nooo why fail??').to.be.arguments;

别名 .Arguments 可以与 .arguments 交换使用。

.equal(val[, msg])

  • @param { Mixed } val
  • @param { String } msg _可选_

断言目标严格地 (===) 等于给定的 val

expect(1).to.equal(1);
expect('foo').to.equal('foo');

在链中更早地添加 .deep 来使用深度相等性。有关深度相等性算法的更多信息,请参见 deep-eql 项目页面:https://github.com/chaijs/deep-eql。

// 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) equals `[1, 2]`
expect([1, 2]).to.deep.equal([1, 2]);
expect([1, 2]).to.not.equal([1, 2]);

在链中更早地添加 .not 来否定 .equal。但是,通常最好断言目标等于其预期值,而不是不等于无数个意外值中的一个。

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

.equal 接受一个可选的 msg 参数,这是一个自定义错误消息,用于在断言失败时显示。该消息也可以作为 expect 的第二个参数给出。

expect(1).to.equal(2, 'nooo why fail??');
expect(1, 'nooo why fail??').to.equal(2);

别名 .equalseq 可以与 .equal 交换使用。

.eql(obj[, msg])

  • @param { Mixed } obj
  • @param { String } msg _可选_

断言目标深度地等于给定的 obj。有关深度相等性算法的更多信息,请参见 deep-eql 项目页面:https://github.com/chaijs/deep-eql。

// 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]);

在链中更早地添加 .not 来否定 .eql。但是,通常最好断言目标深度地等于其预期值,而不是不深度地等于无数个意外值中的一个。

expect({a: 1}).to.eql({a: 1}); // Recommended
expect({a: 1}).to.not.eql({b: 2}); // Not recommended

.eql 接受一个可选的 msg 参数,这是一个自定义错误消息,用于在断言失败时显示。该消息也可以作为 expect 的第二个参数给出。

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

别名 .eqls 可以与 .eql 交换使用。

.deep.equal 断言几乎与 .eql 相同,但有一个区别:.deep.equal 会导致对任何其他在链中跟随的断言也使用深度相等比较。

.above(n[, msg])

  • @param { Number } n
  • @param { String } msg _可选_

断言目标是一个数字或一个日期,分别大于给定的数字或日期 n。但是,通常最好断言目标等于其预期值。

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

在链中更早添加 .lengthOf 以断言目标的 lengthsize 大于给定的数字 n

expect('foo').to.have.lengthOf(3); // Recommended
expect('foo').to.have.lengthOf.above(2); // Not recommended

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

在链中更早添加 .not 以否定 .above

expect(2).to.equal(2); // Recommended
expect(1).to.not.be.above(2); // Not recommended

.above 接受一个可选的 msg 参数,这是一个自定义错误消息,用于在断言失败时显示。该消息也可以作为 expect 的第二个参数给出。

expect(1).to.be.above(2, 'nooo why fail??');
expect(1, 'nooo why fail??').to.be.above(2);

别名 .gt.greaterThan 可以与 .above 交换使用。

.least(n[, msg])

  • @param { Number } n
  • @param { String } msg _可选_

断言目标是一个数字或一个日期,分别大于或等于给定的数字或日期 n。但是,通常最好断言目标等于其预期值。

expect(2).to.equal(2); // Recommended
expect(2).to.be.at.least(1); // Not recommended
expect(2).to.be.at.least(2); // Not recommended

在链中更早添加 .lengthOf 以断言目标的 lengthsize 大于或等于给定的数字 n

expect('foo').to.have.lengthOf(3); // Recommended
expect('foo').to.have.lengthOf.at.least(2); // Not recommended

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

在链中更早添加 .not 以否定 .least

expect(1).to.equal(1); // Recommended
expect(1).to.not.be.at.least(2); // Not recommended

.least 接受一个可选的 msg 参数,这是一个自定义错误消息,用于在断言失败时显示。该消息也可以作为 expect 的第二个参数给出。

expect(1).to.be.at.least(2, 'nooo why fail??');
expect(1, 'nooo why fail??').to.be.at.least(2);

别名 .gte.greaterThanOrEqual 可以与 .least 交换使用。

.below(n[, msg])

  • @param { Number } n
  • @param { String } msg _可选_

断言目标是一个数字或一个日期,分别小于给定的数字或日期 n。但是,通常最好断言目标等于其预期值。

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

在链中更早添加 .lengthOf 以断言目标的 lengthsize 小于给定的数字 n

expect('foo').to.have.lengthOf(3); // Recommended
expect('foo').to.have.lengthOf.below(4); // Not recommended

expect([1, 2, 3]).to.have.length(3); // Recommended
expect([1, 2, 3]).to.have.lengthOf.below(4); // Not recommended

在链中更早添加 .not 以否定 .below

expect(2).to.equal(2); // Recommended
expect(2).to.not.be.below(1); // Not recommended

.below 接受一个可选的 msg 参数,这是一个自定义错误消息,用于在断言失败时显示。该消息也可以作为 expect 的第二个参数给出。

expect(2).to.be.below(1, 'nooo why fail??');
expect(2, 'nooo why fail??').to.be.below(1);

别名 .lt.lessThan 可以与 .below 交换使用。

.most(n[, msg])

  • @param { Number } n
  • @param { String } msg _可选_

断言目标是一个数字或一个日期,分别小于或等于给定的数字或日期 n。但是,通常最好断言目标等于其预期值。

expect(1).to.equal(1); // Recommended
expect(1).to.be.at.most(2); // Not recommended
expect(1).to.be.at.most(1); // Not recommended

在链中更早添加 .lengthOf 以断言目标的 lengthsize 小于或等于给定的数字 n

expect('foo').to.have.lengthOf(3); // Recommended
expect('foo').to.have.lengthOf.at.most(4); // Not recommended

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

在链中更早添加 .not 以否定 .most

expect(2).to.equal(2); // Recommended
expect(2).to.not.be.at.most(1); // Not recommended

.most 接受一个可选的 msg 参数,这是一个自定义错误消息,用于在断言失败时显示。该消息也可以作为 expect 的第二个参数给出。

expect(2).to.be.at.most(1, 'nooo why fail??');
expect(2, 'nooo why fail??').to.be.at.most(1);

别名 .lte.lessThanOrEqual 可以与 .most 交换使用。

.within(start, finish[, msg])

  • @param { Number } start 下界(包含)
  • @param { Number } finish 上界(包含)
  • @param { String } msg _可选_

断言目标是一个数字或一个日期,分别大于或等于给定的数字或日期 start,并且小于或等于给定的数字或日期 finish。但是,通常最好断言目标等于其预期值。

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

在链中更早添加 .lengthOf 以断言目标的 lengthsize 大于或等于给定的数字 start,并且小于或等于给定的数字 finish

expect('foo').to.have.lengthOf(3); // Recommended
expect('foo').to.have.lengthOf.within(2, 4); // Not recommended

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

在链中更早添加 .not 以否定 .within

expect(1).to.equal(1); // Recommended
expect(1).to.not.be.within(2, 4); // Not recommended

.within 接受一个可选的 msg 参数,这是一个自定义错误消息,用于在断言失败时显示。该消息也可以作为 expect 的第二个参数给出。

expect(4).to.be.within(1, 3, 'nooo why fail??');
expect(4, 'nooo why fail??').to.be.within(1, 3);

.instanceof(constructor[, msg])

  • @param { Constructor } constructor
  • @param { String } msg _可选_

断言目标是给定 constructor 的实例。

function Cat () { }

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

在链中更早添加 .not 以否定 .instanceof

expect({a: 1}).to.not.be.an.instanceof(Array);

.instanceof 接受一个可选的 msg 参数,这是一个自定义错误消息,用于在断言失败时显示。该消息也可以作为 expect 的第二个参数给出。

expect(1).to.be.an.instanceof(Array, 'nooo why fail??');
expect(1, 'nooo why fail??').to.be.an.instanceof(Array);

由于 ES5 的限制,.instanceof 在使用 Babel 或 TypeScript 等转译器时可能无法始终按预期工作。特别是,在对内置对象(如 ArrayErrorMap)进行子类化时,它可能会产生意外的结果。有关详细信息,请参阅您的转译器的文档

别名 .instanceOf 可以与 .instanceof 交换使用。

.property(name[, val[, msg]])

  • @param { String } name
  • @param { Mixed } val (可选)
  • @param { String } msg _可选_

断言目标具有具有给定键 name 的属性。

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

当提供 val 时,.property 还会断言该属性的值等于给定的 val

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

默认情况下,使用严格 (===) 相等。在链中更早添加 .deep 以改为使用深度相等。有关深度相等算法的信息,请参阅 deep-eql 项目页面:https://github.com/chaijs/deep-eql。

// 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});

目标的可枚举和不可枚举属性始终包含在搜索中。默认情况下,包含自己的属性和继承的属性。在链中更早添加 .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');
expect({a: 1}).to.not.have.own.property('b');

.deep.own 可以结合使用。

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

在链中添加 .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');

如果 .[] 是实际属性名称的一部分,则可以通过在它们前面添加两个反斜杠来转义它们。

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

.deep.nested 可以组合使用。

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

.own.nested 不能组合使用。

在链中更早添加 .not 以否定 .property

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

但是,在提供 val 时对 .property 进行否定操作很危险。问题在于,它通过断言目标要么没有具有给定键 name 的属性,要么具有具有给定键 name 的属性,但其值不等于给定的 val,从而产生不确定的期望。通常最好识别出预期的确切输出,然后编写一个只接受该确切输出的断言。

当目标预期没有具有给定键 name 的属性时,通常最好断言这一点。

expect({b: 2}).to.not.have.property('a'); // Recommended
expect({b: 2}).to.not.have.property('a', 1); // Not recommended

当目标预期具有具有给定键 name 的属性时,通常最好断言该属性具有其预期值,而不是断言它没有多个非预期值。

expect({a: 3}).to.have.property('a', 3); // Recommended
expect({a: 3}).to.not.have.property('a', 1); // Not recommended

.property 将链中随后所有断言的目标更改为原始目标对象中属性的值。

expect({a: 1}).to.have.property('a').that.is.a('number');

.property 接受一个可选的 msg 参数,该参数是一个自定义错误消息,用于在断言失败时显示。该消息也可以作为 expect 的第二个参数提供。当不提供 val 时,只使用第二种形式。

// Recommended
expect({a: 1}).to.have.property('a', 2, 'nooo why fail??');
expect({a: 1}, 'nooo why fail??').to.have.property('a', 2);
expect({a: 1}, 'nooo why fail??').to.have.property('b');

// Not recommended
expect({a: 1}).to.have.property('b', undefined, 'nooo why fail??');

上面的断言与不提供 val 不一样。相反,它断言目标对象具有一个等于 undefinedb 属性。

断言 .ownProperty.haveOwnProperty 可以与 .own.property 交换使用。

.ownPropertyDescriptor(name[, descriptor[, msg]])

  • @param { String } name
  • @param { Object } descriptor _optional_
  • @param { String } msg _可选_

断言目标具有其自己的属性描述符,该描述符具有给定的键 name。可枚举和不可枚举的属性都包含在搜索中。

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

当提供 descriptor 时,.ownPropertyDescriptor 还断言该属性的描述符与给定的 descriptor 深度相等。有关深度相等算法的信息,请参阅 deep-eql 项目页面:https://github.com/chaijs/deep-eql。

expect({a: 1}).to.have.ownPropertyDescriptor('a', {
  configurable: true,
  enumerable: true,
  writable: true,
  value: 1,
});

在链中更早地添加 .not 以否定 .ownPropertyDescriptor

expect({a: 1}).to.not.have.ownPropertyDescriptor('b');

但是,在提供 descriptor 时对 .ownPropertyDescriptor 进行否定操作很危险。问题在于,它通过断言目标要么没有具有给定键 name 的属性描述符,要么具有具有给定键 name 的属性描述符,但它与给定的 descriptor 不深度相等,从而产生不确定的期望。通常最好识别出预期的确切输出,然后编写一个只接受该确切输出的断言。

当目标预期没有具有给定键 name 的属性描述符时,通常最好断言这一点。

// Recommended
expect({b: 2}).to.not.have.ownPropertyDescriptor('a');

// Not recommended
expect({b: 2}).to.not.have.ownPropertyDescriptor('a', {
  configurable: true,
  enumerable: true,
  writable: true,
  value: 1,
});

当目标预期具有具有给定键 name 的属性描述符时,通常最好断言该属性具有其预期描述符,而不是断言它没有多个非预期描述符。

// Recommended
expect({a: 3}).to.have.ownPropertyDescriptor('a', {
  configurable: true,
  enumerable: true,
  writable: true,
  value: 3,
});

// Not recommended
expect({a: 3}).to.not.have.ownPropertyDescriptor('a', {
  configurable: true,
  enumerable: true,
  writable: true,
  value: 1,
});

.ownPropertyDescriptor 将链中随后所有断言的目标更改为原始目标对象中属性描述符的值。

expect({a: 1}).to.have.ownPropertyDescriptor('a')
  .that.has.property('enumerable', true);

.ownPropertyDescriptor 接受一个可选的 msg 参数,该参数是一个自定义错误消息,用于在断言失败时显示。该消息也可以作为 expect 的第二个参数提供。当不提供 descriptor 时,只使用第二种形式。

// Recommended
expect({a: 1}).to.have.ownPropertyDescriptor('a', {
  configurable: true,
  enumerable: true,
  writable: true,
  value: 2,
}, 'nooo why fail??');

// Recommended
expect({a: 1}, 'nooo why fail??').to.have.ownPropertyDescriptor('a', {
  configurable: true,
  enumerable: true,
  writable: true,
  value: 2,
});

// Recommended
expect({a: 1}, 'nooo why fail??').to.have.ownPropertyDescriptor('b');

// Not recommended
expect({a: 1})
  .to.have.ownPropertyDescriptor('b', undefined, 'nooo why fail??');

上面的断言与不提供 descriptor 不一样。相反,它断言目标对象具有一个与 undefined 深度相等的 b 属性描述符。

别名 .haveOwnPropertyDescriptor 可以与 .ownPropertyDescriptor 交换使用。

.lengthOf(n[, msg])

  • @param { Number } n
  • @param { String } msg _可选_

断言目标的 lengthsize 等于给定的数字 n

expect([1, 2, 3]).to.have.lengthOf(3);
expect('foo').to.have.lengthOf(3);
expect(new Set([1, 2, 3])).to.have.lengthOf(3);
expect(new Map([['a', 1], ['b', 2], ['c', 3]])).to.have.lengthOf(3);

在链中更早地添加 .not 以否定 .lengthOf。但是,通常最好断言目标的 length 属性等于其预期值,而不是不等于多个非预期值。

expect('foo').to.have.lengthOf(3); // Recommended
expect('foo').to.not.have.lengthOf(4); // Not recommended

.lengthOf 接受一个可选的 msg 参数,该参数是一个自定义错误消息,用于在断言失败时显示。该消息也可以作为 expect 的第二个参数提供。

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

.lengthOf 也可以用作语言链,使链中随后所有 .above.below.least.most.within 断言都使用目标的 length 属性作为目标。但是,通常最好断言目标的 length 属性等于其预期长度,而不是断言其 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);

由于兼容性问题,别名 .length 无法直接链接到未调用的方法(例如 .a)。因此,.length 无法在所有情况下与 .lengthOf 交换使用。建议始终使用 .lengthOf 而不是 .length

expect([1, 2, 3]).to.have.a.length(3); // incompatible; throws error
expect([1, 2, 3]).to.have.a.lengthOf(3);  // passes as expected

.match(re[, msg])

  • @param { RegExp } re
  • @param { String } msg _可选_

断言目标与给定的正则表达式 re 相匹配。

expect('foobar').to.match(/^foo/);

在链中更早地添加 .not 以否定 .match

expect('foobar').to.not.match(/taco/);

.match 接受一个可选的 msg 参数,该参数是一个自定义错误消息,用于在断言失败时显示。该消息也可以作为 expect 的第二个参数提供。

expect('foobar').to.match(/taco/, 'nooo why fail??');
expect('foobar', 'nooo why fail??').to.match(/taco/);

别名 .matches 可以与 .match 交换使用。

.string(str[, msg])

  • @param { String } str
  • @param { String } msg _可选_

断言目标字符串包含给定的子字符串 str

expect('foobar').to.have.string('bar');

在链中更早地添加 .not 以否定 .string

expect('foobar').to.not.have.string('taco');

.string 接受一个可选的 msg 参数,该参数是一个自定义错误消息,用于在断言失败时显示。该消息也可以作为 expect 的第二个参数提供。

expect('foobar').to.have.string('taco', 'nooo why fail??');
expect('foobar', 'nooo why fail??').to.have.string('taco');

.keys(key1[, key2[, …]])

  • @param { String | Array | Object } keys

断言目标对象、数组、映射或集合具有给定的键。只有目标自身继承的属性包含在搜索中。

当目标是对象或数组时,键可以作为一个或多个字符串参数、一个单个数组参数或一个单个对象参数提供。在后一种情况下,只有给定对象中的键很重要;值会被忽略。

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

当目标是映射或集合时,每个键都必须作为单独的参数提供。

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 基于目标的类型执行不同的操作,所以在使用 .keys 之前检查目标的类型很重要。有关测试目标类型的更多信息,请参阅 .a 文档。

expect({a: 1, b: 2}).to.be.an('object').that.has.all.keys('a', 'b');

默认情况下,严格 (===) 相等性用于比较映射和集合的键。在链中更早地添加 .deep 以使用深度相等性。有关深度相等算法的信息,请参阅 deep-eql 项目页面:https://github.com/chaijs/deep-eql。

// Target set deeply (but not strictly) has key `{a: 1}`
expect(new Set([{a: 1}])).to.have.all.deep.keys([{a: 1}]);
expect(new Set([{a: 1}])).to.not.have.all.keys([{a: 1}]);

默认情况下,目标必须包含所有给定的键,且不多不少。在链中提前添加 .any,仅要求目标至少包含一个给定的键。此外,在链中提前添加 .not 以否定 .keys。通常最好在否定 .keys 时添加 .any,并在断言 .keys 时不进行否定时使用 .all

否定 .keys 时,首选 .any,因为 .not.any.keys 确切断言了对输出的预期,而 .not.all.keys 会产生不确定的预期。

// Recommended; asserts that target doesn't have any of the given keys
expect({a: 1, b: 2}).to.not.have.any.keys('c', 'd');

// Not recommended; asserts that target doesn't have all of the given
// keys but may or may not have some of them
expect({a: 1, b: 2}).to.not.have.all.keys('c', 'd');

断言 .keys 且不进行否定时,首选 .all,因为 .all.keys 确切断言了对输出的预期,而 .any.keys 会产生不确定的预期。

// Recommended; asserts that target has all the given keys
expect({a: 1, b: 2}).to.have.all.keys('a', 'b');

// Not recommended; asserts that target has at least one of the given
// keys but may or may not have more of them
expect({a: 1, b: 2}).to.have.any.keys('a', 'b');

请注意,默认情况下,当链中既没有 .all 也没有 .any 时,使用的是 .all。但是,通常最好还是添加 .all,因为它可以提高可读性。

// Both assertions are identical
expect({a: 1, b: 2}).to.have.all.keys('a', 'b'); // Recommended
expect({a: 1, b: 2}).to.have.keys('a', 'b'); // Not recommended

在链中提前添加 .include,要求目标的键是预期键的超集,而不是相同的集合。

// 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');

但是,如果组合了 .any.include,则只有 .any 生效。在这种情况下,将忽略 .include

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

可以将自定义错误消息作为 expect 的第二个参数给出。

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

别名 .key 可以与 .keys 交换使用。

.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 会调用目标函数并断言抛出的错误严格 (===) 等于该错误实例。

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/);

在链中提前添加 .not 以否定 .throw

var goodFn = function () {};

expect(goodFn).to.not.throw();

但是,在提供任何参数时否定 .throw 是很危险的。问题在于,它会通过断言目标要么不抛出错误,要么抛出错误但类型不同于给定类型,要么抛出给定类型的错误但消息不包含给定字符串来产生不确定的预期。通常最好识别预期得到的精确输出,然后编写只接受该精确输出的断言。

当目标预期不会抛出错误时,通常最好确切地断言这一点。

var goodFn = function () {};

expect(goodFn).to.not.throw(); // Recommended
expect(goodFn).to.not.throw(ReferenceError, 'x'); // Not recommended

当目标预期会抛出错误时,通常最好断言该错误是预期类型的,且消息包含预期字符串,而不是断言它不是许多意外类型中的一个,且消息不包含某个字符串。

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

expect(badFn).to.throw(TypeError, 'salmon'); // Recommended
expect(badFn).to.not.throw(ReferenceError, 'x'); // Not recommended

.throw 会将链中之后所有断言的目标更改为抛出的错误对象。

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

expect(badFn).to.throw(TypeError).with.property('code', 42);

.throw 接受一个可选的 msg 参数,它是一个自定义错误消息,用于在断言失败时显示。该消息也可以作为第二个参数传递给 expect。当不提供两个参数时,始终使用第二种形式。

var goodFn = function () {};

expect(goodFn).to.throw(TypeError, 'x', 'nooo why fail??');
expect(goodFn, 'nooo why fail??').to.throw();

由于 ES5 中的限制,当使用诸如 Babel 或 TypeScript 这样的转译器时,.throw 可能并不总是按预期工作。特别是在对内置的 Error 对象进行子类化,然后将子类化的构造函数传递给 .throw 时,可能会产生意外的结果。有关详细信息,请参阅您的转译器文档。

请注意使用 throw 断言时的一些常见错误。一个常见的错误是意外地自己调用函数,而不是让 throw 断言为您调用函数。例如,在测试名为 fn 的函数是否会抛出错误时,请提供 fn 而不是 fn() 作为断言的目标。

expect(fn).to.throw();     // Good! Tests `fn` as desired
expect(fn()).to.throw();   // Bad! Tests result of `fn()`, not `fn`

如果您需要断言您的函数 fn 在传递某些参数时会抛出错误,那么请将对 fn 的调用包装在另一个函数中。

expect(function () { fn(42); }).to.throw();  // Function expression
expect(() => fn(42)).to.throw();             // ES6 arrow function

另一个常见的错误是将对象方法(或任何依赖于 this 的独立函数)作为断言的目标。这样做存在问题,因为当 .throw 调用该函数时,this 上下文将丢失;它无法知道 this 应该是什么。解决此问题有两种方法。一种解决方案是将方法或函数调用包装在另一个函数中。另一种解决方案是使用 bind

expect(function () { cat.meow(); }).to.throw();  // Function expression
expect(() => cat.meow()).to.throw();             // ES6 arrow function
expect(cat.meow.bind(cat)).to.throw();           // Bind

最后,值得一提的是,在 JavaScript 中,最佳实践是只抛出 Error 以及 Error 的派生类,例如 ReferenceErrorTypeError 和扩展了 Error 的用户定义对象。其他类型的任何值在初始化时都不会生成堆栈跟踪。尽管如此,throw 断言实际上支持抛出任何类型的 value,而不只是 Error 及其派生类。

别名 .throws.Throw 可以与 .throw 交换使用。

.respondTo(method[, msg])

  • @param { String } method
  • @param { String } msg _可选_

当目标是非函数对象时,.respondTo 断言目标具有名为 method 的方法。该方法可以是自身方法或继承方法,可以是可枚举的,也可以是非可枚举的。

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 将目标视为非函数对象,即使它是函数。因此,它断言目标具有名为 method 的方法,而不是断言目标的 prototype 属性具有名为 method 的方法。

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

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

在不添加 .itself 的情况下,在使用 .respondTo 之前,务必检查目标的类型。有关检查目标类型的详细信息,请参阅 .a 文档。

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

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

在链中提前添加 .not 以否定 .respondTo

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');

别名 .respondsTo 可以与 .respondTo 交换使用。

.itself

强制所有后续链中 .respondTo 断言的行为,即使目标是函数,也将其视为非函数对象。因此,它会导致 .respondTo 断言目标具有给定名称的方法,而不是断言目标的 prototype 属性具有给定名称的方法。

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

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

.satisfy(matcher[, msg])

  • @param { Function } matcher
  • @param { String } msg _可选_

使用目标作为第一个参数调用给定的 matcher 函数,并断言返回的值为真值。

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

在链中更早添加 .not 以否定 .satisfy

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

.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(expected, delta[, msg])

  • @param { Number } expected
  • @param { Number } delta
  • @param { String } msg _可选_

断言目标是一个数字,该数字在给定 +/- delta 范围内,与给定数字 expected 相比。但是,通常最好断言目标等于其预期值。

// 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);

在链中更早添加 .not 以否定 .closeTo

expect(1.5).to.equal(1.5); // Recommended
expect(1.5).to.not.be.closeTo(3, 1); // Not recommended

.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 交换使用。

.members(set[, msg])

  • @param { Array } set
  • @param { String } msg _可选_

断言目标数组具有与给定数组 set 相同的成员。

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

默认情况下,使用严格 (===) 相等性比较成员。在链中更早添加 .deep 以改用深度相等性。有关深度相等性算法的信息,请参见 deep-eql 项目页面:https://github.com/chaijs/deep-eql。

// 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}]);

默认情况下,顺序无关紧要。在链中更早添加 .ordered 以要求成员以相同的顺序出现。

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

默认情况下,两个数组必须具有相同的大小。在链中更早添加 .include 以要求目标的成员是预期成员的超集。请注意,当添加 .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.ordered.include 都可以组合在一起。但是,如果组合了 .include.ordered,则排序从两个数组的开头开始。

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

在链中更早添加 .not 以否定 .members。但是,这样做很危险。问题是,它通过断言目标数组没有与给定数组 set 具有所有相同的成员来创建不确定的预期,但可能具有也可能不具有其中的一些成员。通常最好识别出预期的确切输出,然后编写一个仅接受该确切输出的断言。

expect([1, 2]).to.not.include(3).and.not.include(4); // Recommended
expect([1, 2]).to.not.have.members([3, 4]); // Not recommended

.members 接受一个可选的 msg 参数,该参数是当断言失败时显示的自定义错误消息。消息也可以作为 expect 的第二个参数提供。

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

.oneOf(list[, msg])

  • @param { Array.<*> } list
  • @param { String } msg _可选_

断言目标是给定数组 list 的成员。但是,通常最好断言目标等于其预期值。

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

比较使用严格 (===) 相等性执行。

在链中更早添加 .not 以否定 .oneOf

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

它还可以与 .contain.include 链在一起,它们将适用于数组和字符串

expect('Today is sunny').to.contain.oneOf(['sunny', 'cloudy'])
expect('Today is rainy').to.not.contain.oneOf(['sunny', 'cloudy'])
expect([1,2,3]).to.contain.oneOf([3,4,5])
expect([1,2,3]).to.not.contain.oneOf([4,5,6])

.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]);

.change(subject[, prop[, msg]])

  • @param { String } subject
  • @param { String } prop name _optional_
  • @param { String } msg _可选_

当提供一个参数时,.change 断言给定函数 subject 在调用目标函数之前调用时返回的值与调用之后调用时返回的值不同。但是,通常最好断言 subject 等于其预期值。

var dots = ''
  , addDot = function () { dots += '.'; }
  , getDots = function () { return dots; };

// Recommended
expect(getDots()).to.equal('');
addDot();
expect(getDots()).to.equal('.');

// Not recommended
expect(addDot).to.change(getDots);

当提供两个参数时,.change 断言给定对象 subjectprop 属性的值在调用目标函数之前与调用之后不同。

var myObj = {dots: ''}
  , addDot = function () { myObj.dots += '.'; };

// Recommended
expect(myObj).to.have.property('dots', '');
addDot();
expect(myObj).to.have.property('dots', '.');

// Not recommended
expect(addDot).to.change(myObj, 'dots');

使用严格 (===) 相等性比较之前和之后的值。

在链中更早添加 .not 以否定 .change

var dots = ''
  , noop = function () {}
  , getDots = function () { return dots; };

expect(noop).to.not.change(getDots);

var myObj = {dots: ''}
  , noop = function () {};

expect(noop).to.not.change(myObj, 'dots');

.change 接受一个可选的 msg 参数,该参数是当断言失败时显示的自定义错误消息。消息也可以作为 expect 的第二个参数提供。当不提供两个参数时,始终使用第二种形式。

var myObj = {dots: ''}
  , addDot = function () { myObj.dots += '.'; };

expect(addDot).to.not.change(myObj, 'dots', 'nooo why fail??');

var dots = ''
  , addDot = function () { dots += '.'; }
  , getDots = function () { return dots; };

expect(addDot, 'nooo why fail??').to.not.change(getDots);

.change 还导致所有后续链中的 .by 断言断言数字主题增加了多少或减少了多少。但是,使用 .change.by 很危险。问题是,它通过断言主题要么增加给定的增量,要么减少给定的增量来创建不确定的预期。通常最好识别出预期的确切输出,然后编写一个仅接受该确切输出的断言。

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

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

expect(subtractTwo).to.decrease(myObj, 'val').by(2); // Recommended
expect(subtractTwo).to.change(myObj, 'val').by(2); // Not recommended

别名 .changes 可以与 .change 交换使用。

.increase(subject[, prop[, msg]])

  • @param { String | Function } subject
  • @param { String } prop name _optional_
  • @param { String } msg _可选_

当提供一个参数时,.increase 断言给定函数 subject 在调用目标函数之后调用时返回的值大于在调用之前调用时返回的值。.increase 还导致所有后续链中的 .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

当提供两个参数时,.increase 断言给定对象 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

在链中更早添加 .not 以否定 .increase。但是,这样做很危险。问题是,它通过断言主题要么减少,要么保持不变来创建不确定的预期。通常最好识别出预期的确切输出,然后编写一个仅接受该确切输出的断言。

当预期主题减少时,通常最好断言它减少了预期数量。

var myObj = {val: 1}
  , subtractTwo = function () { myObj.val -= 2; };

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

当预期主题保持不变时,通常最好断言完全是这样。

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

expect(noop).to.not.change(myObj, 'val'); // Recommended
expect(noop).to.not.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]])

  • @param { String | Function } subject
  • @param { String } prop name _optional_
  • @param { String } msg _可选_

当提供一个参数时,.decrease 断言给定函数 subject 在调用目标函数后调用时返回的值小于在调用目标函数之前调用时返回的值。 .decrease 还会导致链中后续的所有 .by 断言断言返回的值小了多少。 通常最好断言返回值减少了预期量,而不是断言它减少了任何量。

var val = 1
  , subtractTwo = function () { val -= 2; }
  , getVal = function () { return val; };

expect(subtractTwo).to.decrease(getVal).by(2); // Recommended
expect(subtractTwo).to.decrease(getVal); // Not recommended

当提供两个参数时,.decrease 断言给定对象 subjectprop 属性的值在调用目标函数后小于之前。

var myObj = {val: 1}
  , subtractTwo = function () { myObj.val -= 2; };

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

在链中更早添加 .not 以否定 .decrease。 但是,这样做很危险。 问题是它通过断言主题要么增加,要么保持不变来创建不确定的期望。 通常最好识别出期望的确切输出,然后编写一个只接受该确切输出的断言。

当主题预计会增加时,通常最好断言它增加了预期量。

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

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

当预期主题保持不变时,通常最好断言完全是这样。

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

expect(noop).to.not.change(myObj, 'val'); // Recommended
expect(noop).to.not.decrease(myObj, 'val'); // Not recommended

.decrease 接受一个可选的 msg 参数,它是一个自定义错误消息,用于在断言失败时显示。 该消息也可以作为 expect 的第二个参数提供。 当不提供两个参数时,始终使用第二种形式。

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

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

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

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

别名 .decreases 可以与 .decrease 交换使用。

.by(delta[, msg])

  • @param { Number } delta
  • @param { String } msg _可选_

当在链中跟随 .increase 断言时,.by 断言 .increase 断言的主题增加了给定的 delta

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

expect(addTwo).to.increase(myObj, 'val').by(2);

当在链中跟随 .decrease 断言时,.by 断言 .decrease 断言的主题减少了给定的 delta

var myObj = {val: 1}
  , subtractTwo = function () { myObj.val -= 2; };

expect(subtractTwo).to.decrease(myObj, 'val').by(2);

当在链中跟随 .change 断言时,.by 断言 .change 断言的主题增加了或减少了给定的 delta。 但是,使用 .change.by 很危险。 问题是它会产生不确定的期望。 通常最好识别出期望的确切输出,然后编写一个只接受该确切输出的断言。

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

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

expect(subtractTwo).to.decrease(myObj, 'val').by(2); // Recommended
expect(subtractTwo).to.change(myObj, 'val').by(2); // Not recommended

在链中更早添加 .not 以否定 .by。 但是,通常最好断言主题按其预期的增量更改,而不是断言它没有按无数个意外增量之一更改。

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

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

// Not recommended
expect(addTwo).to.increase(myObj, 'val').but.not.by(3);

.by 接受一个可选的 msg 参数,它是一个自定义错误消息,用于在断言失败时显示。 该消息也可以作为 expect 的第二个参数提供。

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

expect(addTwo).to.increase(myObj, 'val').by(3, 'nooo why fail??');
expect(addTwo, 'nooo why fail??').to.increase(myObj, 'val').by(3);

.extensible

断言目标是可扩展的,这意味着可以向其添加新属性。 原语永远不可扩展。

expect({a: 1}).to.be.extensible;

在链中更早添加 .not 以否定 .extensible

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

expect(nonExtensibleObject).to.not.be.extensible;
expect(sealedObject).to.not.be.extensible;
expect(frozenObject).to.not.be.extensible;
expect(1).to.not.be.extensible;

可以将自定义错误消息作为 expect 的第二个参数给出。

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

.sealed

断言目标是密封的,这意味着无法向其添加新属性,并且无法重新配置或删除其现有属性。 但是,其现有属性可能仍然可以重新分配到不同的值。 原语总是密封的。

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

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

在链中更早添加 .not 以否定 .sealed

expect({a: 1}).to.not.be.sealed;

可以将自定义错误消息作为 expect 的第二个参数给出。

expect({a: 1}, 'nooo why fail??').to.be.sealed;

.frozen

断言目标被冻结,这意味着无法向其添加新属性,并且无法将其现有属性重新分配到不同的值,重新配置或删除。 原语总是被冻结的。

var frozenObject = Object.freeze({});

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

在链中更早添加 .not 以否定 .frozen

expect({a: 1}).to.not.be.frozen;

可以将自定义错误消息作为 expect 的第二个参数给出。

expect({a: 1}, 'nooo why fail??').to.be.frozen;

.finite

断言目标是一个数字,并且不是 NaN 或正/负 Infinity

expect(1).to.be.finite;

在链中更早添加 .not 以否定 .finite。 但是,这样做很危险。 问题是它通过断言主题要么不是数字,要么是 NaN,要么是正 Infinity,要么是负 Infinity 来创建不确定的期望。 通常最好识别出期望的确切输出,然后编写一个只接受该确切输出的断言。

当目标预计不是数字时,通常最好断言它是预期的类型,而不是断言它不是许多意外类型之一。

expect('foo').to.be.a('string'); // Recommended
expect('foo').to.not.be.finite; // Not recommended

当目标预计是 NaN 时,通常最好断言就是这样。

expect(NaN).to.be.NaN; // Recommended
expect(NaN).to.not.be.finite; // Not recommended

当目标预计是正无穷大时,通常最好断言就是这样。

expect(Infinity).to.equal(Infinity); // Recommended
expect(Infinity).to.not.be.finite; // Not recommended

当目标预计是负无穷大时,通常最好断言就是这样。

expect(-Infinity).to.equal(-Infinity); // Recommended
expect(-Infinity).to.not.be.finite; // Not recommended

可以将自定义错误消息作为 expect 的第二个参数给出。

expect('foo', 'nooo why fail??').to.be.finite;

.fail([message])

.fail(actual, expected, [message], [operator])

  • @param { Mixed } actual
  • @param { Mixed } expected
  • @param { String } message
  • @param { String } operator

抛出失败。

expect.fail();
expect.fail("custom error message");
expect.fail(1, 2);
expect.fail(1, 2, "custom error message");
expect.fail(1, 2, "custom error message", ">");
expect.fail(1, 2, undefined, ">");

.fail([message])

.fail(actual, expected, [message], [operator])

  • @param { Mixed } actual
  • @param { Mixed } expected
  • @param { String } message
  • @param { String } operator

抛出失败。

should.fail();
should.fail("custom error message");
should.fail(1, 2);
should.fail(1, 2, "custom error message");
should.fail(1, 2, "custom error message", ">");
should.fail(1, 2, undefined, ">");