expect(true).to.be.true;
在此代碼中,所有'to','be','true'似乎是來自'expect(true)'的對象響應的屬性。期望().to.be.true在Chai中如何工作?
這些屬性如何工作以便引發異常?
expect(true).to.be.true;
在此代碼中,所有'to','be','true'似乎是來自'expect(true)'的對象響應的屬性。期望().to.be.true在Chai中如何工作?
這些屬性如何工作以便引發異常?
您可以查看源代碼:
[ 'to', 'be', 'been'
, 'is', 'and', 'has', 'have'
, 'with', 'that', 'which', 'at'
, 'of', 'same', 'but', 'does' ].forEach(function (chain) {
Assertion.addProperty(chain);
});
,有一個addProperty
在utils
:
https://github.com/chaijs/chai/blob/master/lib/chai/utils/addProperty.js
有了這個,你可以無限地鏈接這些屬性:.to.be.to.to.to.be.equal()
讓我們創建一個簡單的演示:
假設你有一個assert
對象,與.true()
方法
const assert = {
'true': function (v) {
return !!v
}
}
,並要能夠鏈.to
無限。使用時只需將defineProperty
來定義我們的getter:所以現在
Object.defineProperty(assert, 'to', {
get() {
return assert
}
})
可以
assert.to.to.to.to.true(false)
工作代碼:https://codepen.io/CodinCat/pen/LLzBEX?editors=0012
我在這裏增加了一個更爲複雜的例子:https://codepen.io/CodinCat/pen/dRVjXL?editors=0012
在這個例子中,你可以看到臨時t在.true
屬性中有一些行爲。
我們將expect()
的值存儲在內部__expectObj
和__value
屬性中,然後在.true
的獲取器中對其進行驗證。所以,你可以
expect(false).to.to.to.to.true
其中'true'是一個函數的代碼是多餘的,我相信OP知道如何編寫一個函數。這個問題的實際答案隱藏在一個鏈接後面;請將其移至您的答案。 –
是的,'.true'是一個屬性(不是方法)的情況也是我最感興趣的。總之,'.true'的getter函數在'expect(false).true'中被查找觸發,並且getter函數運行測試...哇,有趣! –
看看chai Assertion的來源,但是tl; dr是Chai在其斷言庫上實現了自己的可鏈接方法。但是,特殊關鍵字只是語法糖,如下面的代碼所示。從字面上看,他們只是被加入,可以鏈接但沒有真正被定義屬性:
/**
* ### Language Chains
*
* The following are provided as chainable getters to improve the readability
* of your assertions.
*
* **Chains**
*
* - to
* - be
* - been
* - is
* - that
* - which
* - and
* - has
* - have
* - with
* - at
* - of
* - same
* - but
* - does
*
* @name language chains
* @namespace BDD
* @api public
*/
[ 'to', 'be', 'been'
, 'is', 'and', 'has', 'have'
, 'with', 'that', 'which', 'at'
, 'of', 'same', 'but', 'does' ].forEach(function (chain) {
Assertion.addProperty(chain);
});
從那裏它實際上看起來的是它明確定義的關鍵字。因此,一個例子是關鍵字.to.be.true
它會看true
as defined在下面的代碼片段
/**
* ### .true
*
* Asserts that the target is strictly (`===`) equal to `true`.
*
* expect(true).to.be.true;
*
* Add `.not` earlier in the chain to negate `.true`. However, it's often best
* to assert that the target is equal to its expected value, rather than not
* equal to `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
*
* A custom error message can be given as the second argument to `expect`.
*
* expect(false, 'nooo why fail??').to.be.true;
*
* @name true
* @namespace BDD
* @api public
*/
Assertion.addProperty('true', function() {
this.assert(
true === flag(this, 'object')
, 'expected #{this} to be true'
, 'expected #{this} to be false'
, flag(this, 'negate') ? false : true
);
});
我認爲它通過javascript的['__defineGetter__'(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/__defineGetter__)接口的工作方式。 –
它的工作原理是因爲他們添加了一堆無所事事,只會增加噪音的虛擬屬性。我會認爲'assert.isTrue()'更具可讀性,絕對不會提示這樣的問題。 –
@MattiVirkkunen是的,如果人們希望代碼是*英文*而不是*英文*我認爲他們應該寫書而不是 – cat