not
對之後的斷言取反:
expect(foo).to.not.equal(\'bar\') expect(goodFn).to.not.throw(Error) expect({ foo: \'baz\' }).to.have.property(\'foo\').and.not.equal(\'bar\')
deep
設置deep標記,然後使用equal和property斷言。該標記可以讓其後的斷言不是比較對像本身,而是遞歸比較對象的鍵值對:
expect(foo).to.deep.equal({ bar: \'baz\' }) expect({foo: {bar: { baz: \'quux\' }}}) .to.have.deep.property(\'foo.bar.baz\', \'quux\')
deep.property中的特殊符號可以使用雙反斜槓進行轉義(第一個反斜槓是在字符串參數中對第二個反斜槓進行轉義,第二個反斜槓用於在property中進行轉義):
var deepCss = {\'.link\': { \'[target]\': 42 }} expect(deepCss).to.have.deep.property(\'\\.link.\\[target\\]\', 42)
any
在keys斷言之前使用any標記(與all相反):
expect(foo).to.have.any.keys(\'bar\', \'baz\')
all
在keys斷言之前使用all標記(與any相反):
expect(foo).to.have.all.keys(\'bar\', \'baz\')
a(type)/an(type)
● type:String,被測試的值的類型。
a和an斷言即可作為語言鏈又可作為斷言使用:
// 類型斷言 expect(\'test\').to.be.a(\'string\'); expect({ foo: \'bar\' }).to.be.an(\'object\'); expect(null).to.be.a(\'null\'); expect(undefined).to.be.an(\'undefined\'); expect(new Error).to.be.an(\'error\'); expect(new Promise).to.be.a(\'promise\'); expect(new Float32Array).to.be.a(\'float32array\'); expect(Symbol).to.be.a(\'symbol\'); // es6 overrides expect({[Symbol.toStringTag]:=>\'foo\'}).to.be.a(\'foo\'); // language chain expect(foo).to.be.an.instanceof(Foo); ** include(value) / contains(value) **
● value:Object/String/Number。
include和contains既可作為屬性類斷言前綴語言鏈又可作為作為判斷數組、字符串是否包含某值的斷言使用。當作為語言鏈使用時,常用於key斷言之前:
expect([1, 2, 3]).to.include(2) expect(\'foobar\').to.include(\'bar\') expect({ foo: \'bar\', hello: \'universe\' }).to.include.keys(\'foo\')
ok
斷言目標為真值:
expect(\'everything\').to.be.ok expect(1).to.be.ok expect(false).to.not.be.ok expect(null).to.not.be.ok
true
斷言目標為true,注意,這裡與ok的區別是不進行類型轉換,只有為true才能通過斷言:
expect(true).to.be.true expect(1)to.not.be.true
false
斷言目標為false:
expect(false).to.be.false expect(0).to.not.be.false
null
斷言目標為null:
expect(null).to.be.null expect(undefined).to.not.be.null
undefined
斷言目標為undefined:
expect(undefine).to.be.undefined expect(null).to.not.be.undefined
NaN
斷言目標為非數字NaN:
expect(\'foo\').to.be.null expect(4)to.not.be.null
exist
斷言目標存在,既非null也非undefined:
var foo = \'hi\', bar = null, baz expect(foo).to.exist expect(bar).to.not.exist expect(baz).to.not.exist
empty
斷言目標的長度為0。對於數組和字符串,它檢查length屬性,對於對象,它檢查可枚舉屬性的數量:
expect().to.be.empty expect(\'\').to.be.empty expect({}).to.be.empty
arguments
斷言目標是一個參數對像arguments:
function test { expect(arguments).to.be.arguments }
equal(value)
● value:Mixed
斷言目標嚴格等於(===)value。另外,如果設置了deep標記,則斷言目標深度等於value:
expect(\'hello\').to.equal(\'hello\') expect(42).to.equal(42) expect(1).to.not.equal(true) expect({foo: \'bar\'}).to.not.equal({foo: \'bar\'}) expect({foo: \'bar\'}).to.deep.equal({ foo: \'bar\' })
eql(value)
● value:Mixed
斷言目標深度等於value,相當於deep.equal(value)的簡寫:
expect({foo: \'bar\'}).to.eql({ foo: \'bar\' }) expect([1, 2, 3]).to.eql([1, 2, 3])
above(value)
● value:Number
斷言目標大於(超過)value:
expect(10).to.be.above(5)
也可接在length後來斷言一個最小的長度。相比直接提供長度的好處是提供了更詳細的錯誤消息:
expect(\'foo\').to.have.length.above(2) expect([1, 2, 3]).to.have.length.above(2)
least(value)
● value:Number
斷言目標不小於(大於或等於)value:
expect(10).to.be.at.least(10)
也可接在length後來斷言一個最小的長度。相比直接提供長度的好處是提供了更詳細的錯誤消息:
expect(\'foo\').to.have.length.of.at.least(3) expect([1, 2, 3]).to.have.length.of.at.least(3)
below(value)
● value:Number
斷言目標小於value:
expect(5).to.be.below(10)
也可接在length後來斷言一個最大的長度。相比直接提供長度的好處是提供了更詳細的錯誤消息:
expect(\'foo\').to.have.length.below(4) expect([1, 2, 3]).to.have.length.below(4)
most(value)
● value:String
斷言目標不大於(小於或等於)value:
expect(5).to.be.at.most(5)
也可接在length後來斷言一個最大的長度。相比直接提供長度的好處是提供了更詳細的錯誤消息:
expect(\'foo\').to.have.length.of.at.most(4) expect([1, 2, 3]).to.have.length.of.at.most(3)
within(start, finish)
● start:Number,下限;
● finish:Number,上限。
斷言目標在某個區間內:
expect(7).to.be.within(5,10)
也可接在length後來斷言一個長度區間。相比直接提供長度的好處是提供了更詳細的錯誤消息:
expect(\'foo\').to.have.length.within(2, 4) expect([1, 2, 3]).to.have.length.within(2, 4)
instanceof(constructor)
● constructor:Constructor,構造函數。
斷言目標是構造函數constructor的一個實例:
var Tea = function (name) { this.name = name }, Chai = new Tea(\'chai\') expect(Chai).to.be.an.instanceof(Tea) expect([1, 2, 3]).to.be.an.instanceof(Array)
property(name, [value])
● name:String,屬性名;
● value:Mixed,可選,屬性值。
斷言目標是否擁有名為name的屬性,如果提供了value則該屬性值還需要嚴格等於(===)value。如果設置了deep標記,則可以使用點「.」和中括號「」來指向對像和數組中的深層屬性:
// 簡單引用 var obj = { foo: \'bar\' } expect(obj).to.have.property(\'foo\') expect(pbj).to.have.property(\'foo\', \'bar\') // 深層引用 var deepObj = { green: { tea: \'matcha\' }, teas: [\'Chai\', \'matcha\', { tea: \'konacha\' }] } expect(deepObj).to.have.deep.property(\'green.tea\', \'matcha\') expect(deepObj).to.have.deep.property(\'teas[1]\', \'matcha\') expect(deepObj).to.have.deep.property(\'teas[2].tea\', \'konacha\')
如果目標是一個數組,還可以直接使用一個或多個數組下標作為name來在嵌套數組中斷言deep.property:
var arr = [ [ \'chai\', \'matcha\', \'konacha\' ], [ { tea: \'chai\' }, { tea: \'matcha\' }, { tea: \'konacha\' } ] ] expect(arr).to.have.deep.property(\'[0][1]\', \'matcha\') expect(arr).to.have.deep.property(\'[1][2].tea\', \'konacha\')
此外,property把斷言的主語(subject)從原來的對象變為當前屬性的值,使得可以在其後進一步銜接其他鏈式斷言(來針對這個屬性值進行測試):
expect(obj).to.have.property(\'foo\') .that.is.a(\'string\') expect(deepObj).to.have.property(\'green\') .that.is.an(\'object\') .that.deep.equals({ tea: \'matcha\' }) expect(deepObj).to.have.property(\'teas\') .that.is.an(\'array\') .with.deep.property(\'[2]\') .that.deep.equals({ tea: \'konacha\' })
只有當設置了deep標記的時候,在property name中的點(.)和中括號()才必須使用雙反斜槓進行轉義(為什麼是雙反斜槓,在前文有提及),當沒有設置deep標記的時候,是不能進行轉義的。
// 簡單指向 var css = { \'.link[target]\': 42 } expect(css).to.have.property(\'.link[target]\', 42) // 深度指向 var deepCss = { \'link\': { \'[target]\': 42 } } expect(deepCss).to.have.deep.property(\'\\.link\\.[target]\', 42)
ownProperty(name)
● name:String,屬性名。
斷言目標擁有名為name的自有屬性:
expect(\'test\').to.have.ownProperty(\'length\')
ownPropertyDescription(name[, descriptor])
● name:String,屬性名;
● descriptor:Object,描述對象,可選。
斷言目標的某個自有屬性存在描述符對象,如果給定了descroptor描述符對象,則該屬性的描述符對像必須與其相匹配:
expect(\'test\').to.have.ownPropertyDescriptor(\'length\') expect(\'test\').to.have.ownPropertyDescriptor(\'length\', { enumerable: false, configrable: false, writeable: false, value: 4 }) expect(\'test\').not.to.have.ownPropertyDescriptor(\'length\', { enumerable: false, configurable: false, writeable: false, value: 3 }) // 將斷言的主語改為了屬性描述符對像 expect(\'test\').to.have.ownPropertyDescriptor(\'length\') .to.have.property(\'enumerable\', false) expect(\'test\').to.have.ownPropertyDescriptor(\'length\') .to.have.keys(\'value\')
length
設置.have.length標記作為比較length屬性值的前綴:
expect(\'foo\').to.have.length.above(2) expect([1, 2, 3]).to.have.length.within(2, 4)
lengthOf(value)`
-value:Number。
斷言目標的length屬性為期望的值:
expect([1, 2, 3]).to.have.lengthOf(3) expect(\'foobar\').to.have.lengthOf(6)
match(regexp)
● regexp:RegExp,正則表達式。
斷言目標匹配到一個正則表達式:
expect(\'foobar\').to.match(/^foo/)
string(string)
● string:String,字符串。
斷言目標字符串包含另一個字符串:
expect(\'foobar\').to.have.string(\'bar\')
keys(key1, [key2], [...])
● key:String | Array | Object屬性名。
斷言目標包含傳入的屬性名。與any、all、contains或者have前綴結合使用會影響測試結果:
● 當與any結合使用時,無論是使用have還是使用contains前綴,目標必須至少存在一個傳入的屬性名才能通過測試。注意,any或者all應當至少使用一個,否則默認為all。
● 當結合all和contains使用時,目標對像必須至少擁有全部傳入的屬性名,但是它也可以擁有其他屬性名。
● 當結合all和have使用時,目標對像必須且僅能擁有全部傳入的屬性名:
// 結合any使用 expect({ foo: 1, bar: 2, baz: 3 }).to.have.any.keys(\'foo\', \'bar\') expect({ foo: 1, bar: 2, baz: 3 }).to.contains.any.keys(\'foo\', \'bar\') // 結合all使用 expect({ foo: 1, bar: 2, baz: 3 }).to.have.all.keys(\'foo\', \'bar\', \'baz\') expect({ foo: 1, bar: 2, baz: 3 }).to.contains.all.keys(\'foo\', \'bar\') // 傳入string expect({ foo: 1, bar: 2, baz: 3 }).to.have.any.keys(\'foo\') // 傳入Array expect({ foo: 1, bar: 2, baz: 3 }).to.have.all.keys([\'foo\', \'bar\', \'baz\']) // 傳入Object expect({ foo: 1, bar: 2, baz: 3 }).to.have.any.keys({ bar: 2, foo: 1 })
throw(constructor)
● constructor:ErrorConstroctor | String | RegExp。
斷言目標函數會拋出一個指定錯誤或錯誤類型(使用instanceOf計算),也可使用正則表達式或者字符串來檢測錯誤消息:
var err = new RefernceError(\'this is a bad function\') var fn = function { throw err } expect(fn).to.throw(ReferenceError) expect(fn).to.throw(Error) expect(fn).to.throw(/bad function/) expect(fn).to.not.throw(\'good function\') expect(fn).to.throw(ReferrenceError, /bad function/) expect(fn).to.throw(err)
注意,當一個拋錯斷言被否定了(前面有not),那麼它會從Error構造函數開始依次檢查各個可能傳入的參數。檢查一個只是消息類型不匹配但是已知的錯誤,合理的方式是先斷言該錯誤存在,然後使用and後斷言錯誤消息不匹配:
expect(fn).to.throw(ReferenceError) .and.not.throw(/good function/)
respondTo(method)
● method:String。
斷言目標類或對像會響應一個方法(存在這個方法):
Klass.prototype.bar = function {} expect(Klass).to.respondTo(\'bar\') expect(obj).to.respondTo(\'bar\')
如果需要檢查一個構造函數是否會響應一個靜態方法(掛載在構造函數本身的方法),請查看itself標記:
Klass.baz = function {} expect(Klass).itself.to.respondTo(\'baz\')
itself
設置itself標記,然後使用respondTo斷言:
function Foo {} Foo.bar = function {} Foo.prototype.baz = function {} expect(Foo).itself.to.respondTo(\'bar\') expect(Foo).itself.not.to.respond(\'baz\')
satisfy(method)
● method:Function,測試器,接受一個參數表示目標值,返回一個布爾值。
斷言目標值能夠讓給定的測試器返回真值:
expect(1).to.satisfy(function (num) { return num > 0 })
closeTo(expected, delta)
● expect:Numbre,期望值;
● delta:Numbre,範圍半徑。
斷言目標數字等於expected,或在期望值的+/−delta範圍內:
expect(1.5).to.be.closeTo(1, 0.5)
members(set)
● set:Array
斷言目標是set的超集,或前者有後者所有嚴格相等(===)的成員。另外,如果設置了deep標記,則成員進行深度比較(include/contains只能接受單個值,但它們的主語除了 是數組,還可以判斷字符串;members則將它們的能力擴展為能夠接受一個數組,但主語只能是數組):
expect([1, 2, 3]).to.include.members([3, 2]) expect([1, 2, 3]).to.not.include.members([3, 2, 8]) expect([4, 2]).to.have.members([2, 4]) expect([5, 2]).to.not.have.members([5, 2, 1]) expect([{ id: 1 }]).to.deep.include.members([{ id: 1 }])
oneOf(list)
● list:Array。
斷言目標值出現在list數組的某個頂層位置(直接子元素,嚴格相等):
expect(\'a\').to.be.oneOf([\'a\', \'b\', \'c\']) expect(9).to.not.be.oneOf([\'z\']) // 嚴格相等,所以對像類的值必須為同一個引用才能被判定為相等 var three = [3] expect([3]).to.not.be.oneOf([1, 2, [3]]) expect(three).to.not.be.oneOf([1, 2, [3]]) expect(three).to.be.oneOf([1, 2, three])
change(object, property)
● object:Object,對像;
● property:String,屬性名。
斷言目標方法會改變指定對象的指定屬性:
var obj = { val: 10 } var fn = function { obj.val += 3 } var noChangeFn = function { return \'bar\' + \'baz\' } expect(fn).to.change(obj, \'val\')
increase(object, property)
● object:Object,對像;
● property:String,屬性名。
斷言目標方法會增加指定對象的屬性:
var obj = { val: 10 } var fn = function { obj.val = 15 } expect(fn).to.increase(obj, val)
decrease(object, property)
● object:Object,對像;
● property:String,屬性名。
斷言目標方法會減少指定對象的屬性:
var obj = { val: 10 } var fn = function { obj.val = 5 } expect(fn).to.decrease(obj, val)
extensible
斷言目標對象是可擴展的(可以添加新的屬性):
var nonExtensibleObject = Object.preventExtensions({}) var sealedObject = Object.seal({}) var frozenObject = Object.freeze({}) expect({}).to.be.extensible expect(nonExtensibleObject).to.not.be.extensible expect(sealObject).to.not.be.extensible expect(frozenObject).to.not.be.extensible
sealed
斷言目標對象是封閉的(無法添加新的屬性並且存在的屬性不能被刪除但可以被修改):
var sealedObject= Object.seal({}) var frozenObject = Object.freeze({}) expect(sealedObject).to.be.sealed expect(frozenObject).to.be.sealed expect({}).to.not.be.sealed
frozen
斷言目標對象是凍結的(無法添加新的屬性並且存在的屬性不能被刪除和修改):
var frozenObject = Object.freeze({}) expect(frozenObject).to.be.frozen expect({}).to.not.be.frozen