【问题标题】:How do I test a decorator which is a wrapper around $timeout?如何测试作为 $timeout 的包装器的装饰器?
【发布时间】:2014-07-11 21:14:02
【问题描述】:

我有以下装饰器,它从$rootScope 中环绕原始$timeout。在控制器内部使用时,它会在作用域被销毁时取消 $timeout 承诺。

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

    $provide.decorator('$rootScope', ['$delegate', function ($delegate) {

        Object.defineProperty($delegate.constructor.prototype, 'timeout', {
            value: function (fn, number, invokeApply) {
                var $timeout = angular.injector(['ng']).get('$timeout'),
                    promise;

                promise = $timeout(fn, number, invokeApply);

                this.$on('$destroy', function () {
                    $timeout.cancel(promise);
                });
            },
            enumerable: false
        });

        return $delegate;
    }]);

}]);

但是我该如何正确地进行单元测试呢?我有点看到我应该在这里做 2 个测试... 1) 检查是否在调用 $rootScope.timeout() 时调用了原始的 $timeout 以及 2) 检查在销毁范围时是否取消了承诺。

这是我目前的测试套件:

describe('MyApp', function () {
    var $rootScope;

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

        inject(['$rootScope', function (_$rootScope_) {
            $rootScope = _$rootScope_;
        }]);
    });

    describe('$timeout', function () {
        it('<something>', function () {
            $rootScope.timeout(function () {}, 2500);

            // Test if the real $timeout was called with above parameters

            $rootScope.$destroy();

            // Test if the $timeout promise was destroyed
        });
    });

});

这样做的唯一一件事就是给我 100% 的覆盖率。但这不是我想要的……我该如何正确测试呢?

【问题讨论】:

    标签: angularjs unit-testing karma-jasmine angular-mock angular-decorator


    【解决方案1】:

    由于没有人能够帮助我,而我真的很想完成这项工作,我最终找到了自己的解决方案。我不确定这是不是最好的解决方案,但我认为它可以解决问题。

    我是这样解决的:

    describe('MyApp', function () {
        var $rootScope,
            $timeout,
            deferred;
    
        beforeEach(function () {
            module('MyApp');
    
            inject(['$rootScope', '$q', function (_$rootScope_, _$q_) {
                $rootScope = _$rootScope_;
                deferred = _$q_.defer();
            }]);
    
            $timeout = jasmine.createSpy('$timeout', {
                cancel: jasmine.createSpy('$timeout.cancel')
            }).and.returnValue(deferred.promise);
    
            spyOn(angular, 'injector').and.returnValue({
                get: function () {
                    return $timeout;
                }
            });
        });
    
        describe('$timeout', function () {
            it('should set the timeout with the specified arguments', function () {
                $rootScope.timeout(angular.noop, 250, false);
                expect($timeout).toHaveBeenCalledWith(angular.noop, 250, false);
            });
    
            it('should cancel the timeout on scope destroy event', function () {
                $rootScope.timeout(angular.noop, 250, false);
                $rootScope.$destroy();
    
                expect($timeout.cancel).toHaveBeenCalledWith(deferred.promise);
            });
        });
    
    });
    

    【讨论】:

      猜你喜欢
      • 2019-07-09
      • 1970-01-01
      • 1970-01-01
      • 2017-08-27
      • 2011-02-13
      • 2017-08-20
      • 1970-01-01
      • 2012-11-01
      • 1970-01-01
      相关资源
      最近更新 更多