BDD

BDD 風格有 expectshould。兩者都使用相同的可鏈式語言來建構斷言,但它們在最初建構斷言的方式上有所不同。請查看風格指南以進行比較。

API 參考

語言鏈

以下提供可鏈式 getter 以提高斷言的可讀性。

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

.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 _optional_

斷言目標的類型等於給定的字串 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 _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 目標)。 有關深度相等演算法的資訊,請參閱 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;

當目標是 map 或 set 時,.empty 斷言目標的 size 屬性嚴格等於 0

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

當目標是非函數物件時,.empty 斷言目標沒有任何自身可列舉的屬性。具有 Symbol 型鍵的屬性將排除在計數之外。

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 _optional_

斷言目標與給定的 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 _optional_

斷言目標與給定的 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 _optional_

斷言目標是一個數字或日期,分別大於給定的數字或日期 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 _optional_

斷言目標是一個數字或日期,分別大於或等於給定的數字或日期 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 _optional_

斷言目標是一個數字或日期,分別小於給定的數字或日期 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 _optional_

斷言目標是一個數字或日期,分別小於或等於給定的數字或日期 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 _optional_

斷言目標是一個數字或日期,分別大於或等於給定的數字或日期 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 _optional_

斷言目標是給定 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 的限制,當使用 Babel 或 TypeScript 等轉譯器時,.instanceof 可能不總是按預期工作。特別是,當子類化內建物件(例如 ArrayErrorMap)時,可能會產生意想不到的結果。有關詳細資訊,請參閱您的轉譯器文件

別名 .instanceOf 可以與 .instanceof 互換使用。

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

  • @param { String } name
  • @param { Mixed } val (選用)
  • @param { String } msg _optional_

斷言目標具有帶有給定鍵 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 _可選的_
  • @param { String } msg _optional_

斷言目標具有具有給定鍵 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 _optional_

斷言目標的 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 _optional_

斷言目標與給定的正規表示式 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 _optional_

斷言目標字串包含給定的子字串 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');

預設情況下,會使用嚴格 ( === ) 相等性來比較 map 和 set 的鍵。在鏈中較早的位置添加 .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 中,最佳實務是僅擲出 ErrorError 的衍生項目,例如 ReferenceErrorTypeError 和擴充 Error 的使用者定義物件。當初始化時,沒有其他類型的值會產生堆疊追蹤。話雖如此,throw 斷言在技術上支援擲出任何類型的值,而不僅僅是 Error 及其衍生項目。

別名 .throws.Throw 可以與 .throw 互換使用。

.respondTo(method[, msg])

  • @param { String } method
  • @param { String } msg _optional_

當目標為非函式物件時,.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 _optional_

使用目標作為第一個參數來調用給定的 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 _optional_

斷言目標是一個數字,且在給定數字 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);

在鏈中較早加入 .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 _optional_

斷言目標陣列具有與給定陣列 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 _optional_

斷言目標是給定陣列 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 _optional_

當提供一個參數時,.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 很危險。問題在於它創建了不確定的期望,即斷言主體要么增加了給定的 delta,要么減少了給定的 delta。通常最好識別預期的確切輸出,然後編寫一個僅接受該確切輸出的斷言。

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 _optional_

當提供一個參數時,.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 _optional_

當提供一個參數時,.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 _optional_

當在鏈式調用中跟隨 .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 的斷言。然而,通常最好斷言主體變更了預期的 delta 值,而不是斷言它沒有變更為無數個非預期的 delta 值之一。

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 時,通常最好確切地斷言它為 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, ">");