断言函数已执行

时间:2016-03-01 23:18:07

标签: knockout.js qunit

我正在尝试对一个订阅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

});

我的问题是:当observable被更改时,如何断言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);
    }
}

1 个答案:

答案 0 :(得分:0)

你应该意识到你在扩展器中有很重的依赖性:qb.analytics。目前,您(通过副作用)还在测试时,只需要想要来测试一个单元:扩展程序。

我可以给你至少三个基本选项来处理这个问题:

  1. qb的拒绝因素排除在外,并以某种方式将其注入您的扩展程序。然后,您的测试可以注入有助于断言的模拟。
  2. 使用像SinonJS这样的间谍/模拟框架。我承认,由于缺乏SinonJS和类似框架的经验,我不能100%确定这种方法是否会得到回报。
  3. 测试中的Monkey patch qb以帮助断言。
  4. 后一种方法有点直率,但它很简单。以下是它的工作原理:

    (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>
    &#13;
    &#13;
    &#13;