如何使用Jasmine(Angular js)对自定义装饰器进行单元测试

时间:2015-07-09 09:32:37

标签: javascript angularjs unit-testing jasmine

所以我在app config中有这样的装饰:

    angular.module('app').config(['$provide', function ($provide) {

    $provide.decorator('$rootScope', ['$delegate', function ($delegate) {
        $delegate.constructor.prototype.$onRootScope = function (name, listener) {
            var unsubscribe = $delegate.$on(name, listener);
            this.$on('$destroy', unsubscribe);
        };

        $delegate.constructor.prototype.$watchRootScope = function (name, listener) {
            var unsubscribe = $delegate.$watch(name, listener);
            this.$on('$destroy', unsubscribe);
        };

        $delegate.constructor.prototype.$watchAfterLoad = function (watchExpression, listener, objectEquality) {
            var initialLoad = true;
            this.$watch(watchExpression, function () {
                if (initialLoad) {
                    // note: this obviously runs outside of angular, so sometimes the timeout could run after initial load
                    setTimeout(function () { initialLoad = false; }, 25);
                } else {
                    listener.apply(this, arguments);
                }
            }, objectEquality);
        };

        return $delegate;
    }]);

}]);

正如你所看到的,这个装饰器让我使用$ scope。$ onRootScope而不是$ rootScope。$ on并负责在范围破坏事件中删除自动侦听器......

当我单元测试我的代码哪个逻辑包含$ scope。$ onRootScope我得到这样的错误: TypeError:undefined不是构造函数(评估'范围。$ onRootScope')在

在每次测试之前,我都要加载所有必需的模型并进行注射,看起来像这样〜:

beforeEach(function () {
    inject(function (_$rootScope_) {
        $rootScope = _$rootScope_;
    });
});

我该如何克服这个问题? 有没有办法模拟/模仿$ scope。$ onRootScope行为?

我对单元测试和新功能都很陌生。 Jasmine很抱歉没有很好的格式化问题。

编辑#1:

我在模拟我的$ scope对象(var $ scope = {...})之前将它作为参数传递给我正在测试的服务方法我可以通过简单地定义$ scope方法来避免错误:

$scope = {
   ...
   $onRootScope: function() {}
}

还在等待一些更好的想法: - )

1 个答案:

答案 0 :(得分:2)

我认为你需要根据装饰的$scope建立你的$rootScope,而不是创建一个新的虚拟对象。

像这样:

var $root, $scope;

beforeEach(function () {
  module('app');

  inject(function ($rootScope) {
    $root  = $rootScope;
    $scope = $root.$new();
  });
});

it('should have the expected property', function () {
  expect($scope.constructor.prototype).to.have.property('$watchRootScope');
});

我很快就找到了我之前放在一起的迷你书的spec suite的链接,做了与你现在大致相同的事情。