How to unit test custom decorator with Jasmine (Angular js)

流过昼夜 提交于 2020-01-15 06:18:22

问题


So I have such decorator in 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;
    }]);

}]);

As you can see this decorator lets me use $scope.$onRootScope instead of $rootScope.$on and takes care of automatic listeners removal on scope destroy event...

When I unit test my code which logic contains $scope.$onRootScope I'm getting such error: TypeError: undefined is not a constructor (evaluating 'scope.$onRootScope') in

Before each test I'm loading all required models and do inject which looks like this ~:

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

How should I overcome this problem? Is there a way to mock / mimic $scope.$onRootScope behaviour?

I'm quite new to unit testing & Jasmine so sorry for not very nicely formatted question.

EDIT #1:

As I'm mocking my $scope object (var $scope = {...}) before passing it as argument to service method which I'm testing I can avoid error by simply defining $scope method:

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

Still awaiting for some better ideas :-)


回答1:


I believe you need to build your $scope based off of the decorated $rootScope, as opposed to creating a new dummy object.

Like so:

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');
});

I'll chuck in a link to the spec suite of a mini-lib I put together some time ago, doing roughly the same thing you are now.



来源:https://stackoverflow.com/questions/31313554/how-to-unit-test-custom-decorator-with-jasmine-angular-js

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!