【问题标题】:How to unit test custom decorator with Jasmine (Angular js)如何使用 Jasmine(Angular js)对自定义装饰器进行单元测试
【发布时间】:2015-09-27 14:18:53
【问题描述】:

所以我在应用配置中有这样的装饰器:

    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 is not a constructor (evalating 'scope.$onRootScope') in

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

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

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

我对单元测试和 Jasmine 很陌生,很抱歉问题的格式不是很好。

编辑#1:

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

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

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

【问题讨论】:

    标签: javascript angularjs unit-testing jasmine


    【解决方案1】:

    我相信您需要基于装饰的$rootScope 构建您的$scope,而不是创建一个新的虚拟对象。

    像这样:

    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 的链接,所做的事情与您现在大致相同。

    【讨论】:

    • 谢谢,你让我走上了正确的道路 :) 我的目标不是测试该属性是否存在,而是让它发挥作用。 $scope = $root.$new(); - 我不知道你可以创建这样的范围,所以我将 $scope 模拟为简单的对象......显然缺少构造函数 $onRootScope ......感谢您的回答!
    猜你喜欢
    • 2016-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-29
    相关资源
    最近更新 更多