2016-03-01 54 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>