BDD
BDD 風格有 expect
和 should
。兩者都使用相同的可鏈式語言來建構斷言,但它們在最初建構斷言的方式上有所不同。請查看風格指南以進行比較。
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])
斷言目標的類型等於給定的字串 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])
當目標是字串時, .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
斷言目標不嚴格 ( ===
) 等於 null
或 undefined
。然而,通常最好斷言目標等於其預期值。
expect(1).to.equal(1); // Recommended
expect(1).to.exist; // Not recommended
expect(0).to.equal(0); // Recommended
expect(0).to.exist; // Not recommended
在鏈式調用中較早的位置加入 .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])
斷言目標與給定的 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);
別名 .equals
和 eq
可以與 .equal
互換使用。
.eql(obj[, 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])
斷言目標是一個數字或日期,分別大於給定的數字或日期 n
。然而,通常最好斷言目標等於其預期值。
expect(2).to.equal(2); // Recommended
expect(2).to.be.above(1); // Not recommended
在鏈中較早加入 .lengthOf
,以斷言目標的 length
或 size
大於給定的數字 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])
斷言目標是一個數字或日期,分別大於或等於給定的數字或日期 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
,以斷言目標的 length
或 size
大於或等於給定的數字 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])
斷言目標是一個數字或日期,分別小於給定的數字或日期 n
。然而,通常最好斷言目標等於其預期值。
expect(1).to.equal(1); // Recommended
expect(1).to.be.below(2); // Not recommended
在鏈中較早加入 .lengthOf
,以斷言目標的 length
或 size
小於給定的數字 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])
斷言目標是一個數字或日期,分別小於或等於給定的數字或日期 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
,以斷言目標的 length
或 size
小於或等於給定的數字 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])
斷言目標是一個數字或日期,分別大於或等於給定的數字或日期 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
,以斷言目標的 length
或 size
大於或等於給定的數字 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])
斷言目標是給定 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
可能不總是按預期工作。特別是,當子類化內建物件(例如 Array
、Error
和 Map
)時,可能會產生意想不到的結果。有關詳細資訊,請參閱您的轉譯器文件
- (Babel)
- (TypeScript)
別名 .instanceOf
可以與 .instanceof
互換使用。
.property(name[, val[, 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
是不同的。相反,它斷言目標物件具有一個等於 undefined
的 b
屬性。
斷言 .ownProperty
和 .haveOwnProperty
可以與 .own.property
互換使用。
.ownPropertyDescriptor(name[, descriptor[, 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])
斷言目標的 length
或 size
等於給定的數字 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])
斷言目標與給定的正規表示式 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])
斷言目標字串包含給定的子字串 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[, …]])
斷言目標物件、陣列、映射或集合具有給定的鍵。搜尋中僅包含目標的自有繼承屬性。
當目標為物件或陣列時,可以將鍵作為一個或多個字串參數、單個陣列參數或單個物件參數提供。在後一種情況下,只有給定物件中的鍵才重要;值會被忽略。
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
時,可能會產生意外的結果。有關詳細資訊,請參閱轉譯器的文件
- (Babel)
- (TypeScript)
使用 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
的衍生項目,例如 ReferenceError
、TypeError
和擴充 Error
的使用者定義物件。當初始化時,沒有其他類型的值會產生堆疊追蹤。話雖如此,throw
斷言在技術上支援擲出任何類型的值,而不僅僅是 Error
及其衍生項目。
別名 .throws
和 .Throw
可以與 .throw
互換使用。
.respondTo(method[, 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])
使用目標作為第一個參數來調用給定的 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])
斷言目標是一個數字,且在給定數字 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])
斷言目標陣列具有與給定陣列 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])
斷言目標是給定陣列 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]])
當提供一個參數時,.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
會斷言在調用目標函式之前,給定物件 subject
的 prop
屬性的值,與調用目標函式之後的值不同。
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]])
當提供一個參數時,.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
會斷言給定物件 subject
的 prop
屬性值,在調用目標函數之後,會比調用之前來得大。
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]])
當提供一個參數時,.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
會斷言給定物件 subject
的 prop
屬性值,在調用目標函數之後,會比調用之前來得小。
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])
當在鏈式調用中跟隨 .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])
拋出失敗。
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])
拋出失敗。
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, ">");