2017-06-26 23 views
18
expect(true).to.be.true; 

在此代碼中,所有'to','be','true'似乎是來自'expect(true)'的對象響應的屬性。期望().to.be.true在Chai中如何工作?

這些屬性如何工作以便引發異常?

+0

我認爲它通過javascript的['__defineGetter__'(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/__defineGetter__)接口的工作方式。 –

+5

它的工作原理是因爲他們添加了一堆無所事事,只會增加噪音的虛擬屬性。我會認爲'assert.isTrue()'更具可讀性,絕對不會提示這樣的問題。 –

+1

@MattiVirkkunen是的,如果人們希望代碼是*英文*而不是*英文*我認爲他們應該寫書而不是 – cat

回答

16

您可以查看源代碼:

[ 'to', 'be', 'been' 
    , 'is', 'and', 'has', 'have' 
    , 'with', 'that', 'which', 'at' 
    , 'of', 'same', 'but', 'does' ].forEach(function (chain) { 
    Assertion.addProperty(chain); 
}); 

,有一個addPropertyutils
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 
+1

其中'true'是一個函數的代碼是多餘的,我相信OP知道如何編寫一個函數。這個問題的實際答案隱藏在一個鏈接後面;請將其移至您的答案。 –

+0

是的,'.true'是一個屬性(不是方法)的情況也是我最感興趣的。總之,'.true'的getter函數在'expect(false).true'中被查找觸發,並且getter函數運行測試...哇,有趣! –

7

看看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 
    ); 
    }); 
相關問題