2016-03-01 68 views
1

我想單元測試一個訂閱ko.observable的Knockout JS擴展函數(導致它在值更改時運行)。爲了測試它是否正常工作,我需要驗證在ko.observable更改時執行擴展程序功能。斷言函數被執行

這裏是我的測試,到目前爲止:

test("ko.extenders.addFieldTrackingGA", function() { 

    //arrange 
    var testObservable = ko.observable(1).extend({ 
     addFieldTrackingGA: "Some button was clicked" 
    }); 

    //act 
    testObservable(5); 

    //assert 

}); 

我的問題是:我怎麼可以斷言,當觀察到的改變是ko.extenders.addFieldTrackingGA被執行?

這裏是我想確認執行代碼:

Knockoutextension:

ko.extenders.addFieldTrackingGA = function (target, option) { 
    target.subscribe(function (newValue) { 
     if (newValue) { 
      qb.Utils.Analytics().trackEvent(qb.Utils.Analytics().product, 
              "form click", 
              option, 
              false); 
     } 
    }); 
    return target; 
}; 

qb.analystics:

/** 
* Event = e.g. 'trackEvent' 
* Category = e.g. 'error_message_home' 
* Action = fieldName 
* Label = 'some message' 
* ignoreMultiple = false | true | {blank} - if true, gtm actions that are fired more than once will be ignored, defaults to true. 
*/ 
var _pushGTM = function (event, category, action, label, ignoreMultiple) { 
    if (typeof dataLayer !== 'undefined') { // Add test for dataLayer as breaking Qunit 

     ignoreMultiple = ignoreMultiple === undefined ? true : ignoreMultiple; 

     if (_.contains(pushedGTM, action + label) && ignoreMultiple) { // Make sure event doesn't get fired more than once, only fire it the first time 
      return; 
     } 

     var gtmObject = { 
      'event': event, 
      'eventDetails.category': category, // Push the value depending on the form (car/house/contents) 
      'eventDetails.action': action,  // Push the form field name.(If there is no field name push "No_field" 
      'eventDetails.label': label   // Please push the exact error string. 
     } 

     if (ignoreMultiple) { 
      pushedGTM.push(action + label); 
     } 

     _pushGTMObject(gtmObject); 
    } 
} 

回答

0

你應該意識到,你在一個相當沉重的依賴你的擴展:qb.analytics。目前你(副作用)也測試,當你只有想要測試一個單元:擴展。

我可以給你至少有三個基本的選擇來處理這個:

  1. 因子出dendency上qb並以某種方式注入到你的擴展。然後你的測試可以注入有助於斷言的模擬。
  2. 使用一些類似SinonJS的間諜/模擬框架。我承認,由於缺乏SinonJS和類似框架的經驗,我不能100%確定這種方法是否會取得成功。
  3. 猴子補丁qb在您的測試中,以幫助斷言。

後一種方法有點生硬,但它很直接。下面是它如何工作:

(function() { 
    "use strict"; 

    var trackEventFn = function() { }; 

    QUnit.module("Mymodule", { 
    beforeEach: function() { 
     window.qb = { 
     Utils: { 
      Analytics: function() { 
       return { trackEvent: trackEventFn }; 
      } 
     } 
     }; 
    } 
    }); 

    QUnit.test("ko.extenders.addFieldTrackingGA", function(assert) { 
    // arrange 
    var testObservable = ko.observable(1).extend({ 
     addFieldTrackingGA: "Some button was clicked" 
    }); 

    // prepare assertion  
    trackEventFn = function(prod, event, option, somebool) { 
     assert.ok(true); 
     // You can also assert on the argument values here 
    } 
    assert.expect(1); // Or more than 1, depending on the above 

    // act 
    testObservable(5); 
    }); 

}()); 

這裏是一個完整的演示:

window.qb = { 
 
    Utils: { 
 
    Analytics: function() { 
 
     return { trackEvent: function() { } }; 
 
    } 
 
    } 
 
}; 
 

 
ko.extenders.addFieldTrackingGA = function (target, option) { 
 
    target.subscribe(function (newValue) { 
 
    if (newValue) { 
 
     qb.Utils.Analytics().trackEvent(qb.Utils.Analytics().product, 
 
             "form click", 
 
             option, 
 
             false); 
 
    } 
 
    }); 
 
    return target; 
 
}; 
 

 
(function() { 
 
    "use strict"; 
 

 
    var trackEventFn = function() { }; 
 

 
    QUnit.module("Mymodule", { 
 
    beforeEach: function() { 
 
     window.qb = { 
 
     Utils: { 
 
      Analytics: function() { 
 
      return { trackEvent: trackEventFn }; 
 
      } 
 
     } 
 
     }; 
 
    } 
 
    }); 
 

 
    QUnit.test("ko.extenders.addFieldTrackingGA", function(assert) { 
 
    // arrange 
 
    var testObservable = ko.observable(1).extend({ 
 
     addFieldTrackingGA: "Some button was clicked" 
 
    }); 
 

 
    // prepare assertion  
 
    trackEventFn = function(prod, event, option, somebool) { 
 
     assert.ok(true); 
 
     // You can also assert on the argument values here 
 
    } 
 
    assert.expect(1); // Or more than 1, depending on the above 
 

 
    // act 
 
    testObservable(5); 
 
    }); 
 

 
}());
<link href="https://cdnjs.cloudflare.com/ajax/libs/qunit/1.18.0/qunit.min.css" rel="stylesheet"/> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/qunit/1.18.0/qunit.min.js"></script> 
 

 
<div id="qunit"></div> 
 
<div id="qunit-fixture"></div>