如何在装饰角度时防止令人讨厌的副作用$ exceptionHandler?

时间:2015-12-16 18:13:10

标签: javascript angularjs jasmine karma-runner

对于自定义服务器端日志记录我正在包装angulars $ exceptionHandler,就像在许多地方所描述的那样,包括stackoverflow和angular docs(有变化,但它们基本上做同样的事情):

loggingModule.config(function ($provide) {
    $provide.decorator('$exceptionHandler', function ($delegate, ExceptionLoggingService) {
        return function () {
            // Call our own ExceptionLoggingService
            ExceptionLoggingService.apply(null, arguments);
            // Call the original
            $delegate.apply(null, arguments);
        };
    });
});

然而,这导致$ exceptionHandler在karma / jasmine单元测试期间没有抛出任何错误。

这可以通过使用this test taken from the angular docs来解释,当模块没有修饰时运行正常,但是当它完成时它们都会失败:

beforeEach(module('logging'));

describe('$exceptionHandlerProvider', function () {
    // testing standard behaviour of $exceptionHandler
    // see https://docs.angularjs.org/api/ngMock/service/$exceptionHandler
    it('should capture log messages and exceptions', function () {
        module(function ($exceptionHandlerProvider) {
            $exceptionHandlerProvider.mode('log');
        });

        inject(function ($log, $exceptionHandler, $timeout) {
            $timeout(function () {
                $log.log(1);
            });
            $timeout(function () {
                $log.log(2);
                throw 'banana peel';
            });
            $timeout(function () {
                $log.log(3);
            });
            expect($exceptionHandler.errors).toEqual([]);
            expect($log.assertEmpty());
            $timeout.flush();
            expect($exceptionHandler.errors).toEqual(['banana peel']);
            expect($log.log.logs).toEqual([[1], [2], [3]]);
        });
    });
});

知道如何修复此行为吗?还check out this plunkr

我使用角#1.3.14

1 个答案:

答案 0 :(得分:1)

来自$exceptionHandler的{​​{1}}函数具有指向数组的ngMock属性。

装饰器返回的函数没有该属性:

error

所以这将失败:

return function () {

  ExceptionLoggingService.apply(null, arguments);

  $delegate.apply(null, arguments);
};

这是一个有希望实现的实现:

expect($exceptionHandler.errors).toEqual([]);

作为一个注释,您应该始终确保在装饰时这样做。 app.config(function($provide) { $provide.decorator('$exceptionHandler', ['$delegate', 'ExceptionLoggingService', function($delegate, ExceptionLoggingService) { var decoratedExceptionHandler = function() { ExceptionLoggingService.apply(this, arguments); return $delegate.apply(this, arguments); }; for (var key in $delegate) { if (!$delegate.hasOwnProperty(key)) continue; decoratedExceptionHandler[key] = $delegate[key]; } return decoratedExceptionHandler; } ]); }); 的真正实现可能目前没有任何属性,但您永远不知道它将来是否会有。 $exceptionHandler服务是您必须执行此操作的一个示例,因为它具有内部用于使视图动画有效的属性。