单元测试AngularJS提供装饰器

时间:2015-04-18 20:07:35

标签: angularjs unit-testing

我已经装饰了Angular的简单$ log实现,因此我可以在特定级别登录。

/**
 *  There are 7 Application logging levels which are:
 *  OFF:    0,
 *  ERROR: 20,
 *  WARN:  30,
 *  INFO:  40,
 *  DEBUG: 50,
 *  LOG:   60,
 *  ALL:  100
 *
 *  To set the logging level to debug:
 *  currentLogLevel = LOG_LEVEL.DEBUG;
 *
 *  Set it to error:
 *  currentLogLevel = LOG_LEVEL.ERROR;
 *
 *  ERROR -> ERROR
 *  WARNING -> WARNING & ERROR
 *  INFO -> INFO, WARNING & ERROR
 *  DEBUG -> DEBUG, INFO, WARNING & ERROR
 *  LOG -> LOG, DEBUG, INFO, WARNING & ERROR
 */
angular.module( 'Logger' ).config( function( $provide ) {

  $provide.decorator( '$log', function( $delegate, LOG_LEVEL ) {

   var currentLogLevel = LOG_LEVEL.WARNING, // Will only log warnings & errors
        log   = $delegate.log,
        debug = $delegate.debug,
        info  = $delegate.info,
        warn  = $delegate.warn,
        error = $delegate.error;

    function attemptToLog( requestLevel, msg ) {
        if( currentLogLevel >= LOG_LEVEL[requestLevel] ) {
            switch( requestLevel ) {
                case 'LOG': log( msg );
                    break;
                case 'DEBUG': debug( msg );
                    break;
                case 'INFO': info( msg );
                    break;
                case 'WARN': warn( msg );
                    break;
                case 'ERROR': error( msg );
                    break;
            }
        }
    }

    $delegate.log = function( msg ) {
        attemptToLog( 'LOG', msg );
    };

    $delegate.debug = function( msg ) {
        attemptToLog('DEBUG', msg);
    };

    $delegate.info = function( msg ) {
        attemptToLog('INFO', msg );
    };

    $delegate.warn = function( msg ) {
        attemptToLog( 'WARN', msg );
    };

    $delegate.error = function( msg ) {
        attemptToLog( 'ERROR', msg );
    };

    return $delegate;
 });

以下是日志级别:

angular.module( 'Logger' )
    .constant('LOG_LEVEL', {
        OFF:    0,
        ERROR: 20,
        WARN:  30,
        INFO:  40,
        DEBUG: 50,
        LOG:   60,
        ALL:  100
    });

一切都很好。我遇到的问题是如何测试它。到目前为止,我有这个:

describe('Testing a decorator', function() {

    var log;

    beforeEach(module('Logger'));

    beforeEach(module(function ($provide) {

        $provide.decorator('$log', function ($delegate) {

        ['log', 'debug', 'info', 'warn', 'error'].forEach(function(logLevel) {
             $delegate[logLevel].logs = [];
           });

           return $delegate;
        });
    }));

    beforeEach(inject(function (_$log_) {
        log = _$log_;
    }));

    it('should log warn', function () {
        log.warn('Logging message');
        // Expect warn to be logged
    });

    it('should log error', function () {
        log.error('Logging message');
        // Expect error to be logged
    });

    it('should not log anything', function () {
        log.info('Logging message');
        // Expect no logging whatsoever
    });
});

我真的不知道如何测试这个,所以任何想法都会很棒。也许我必须改变实施。

另外,我需要一种更好的方法来设置当前的日志级别,但是,我只限于常量。目前我无法想到更好/更灵活的解决方案。

干杯。

更新:我找到了一个很好的解决方案:

describe('Testing a decorator', function() {

    beforeEach(module('Logger'));

    beforeEach(module(function ($provide) {

        $provide.decorator('$log', function ($delegate) {

            ['log', 'debug', 'info', 'warn', 'error'].forEach(function(logLevel) {
                $delegate[logLevel].logs = [];
            });

            return $delegate;
        });
    }));

    describe('Logging at the various levels (log, debug, info, warn, error)', function() {

    beforeEach(inject(function ($log) {
        $log.log('log');
        $log.debug('debug');
        $log.info('info');
        $log.warn('warn');
        $log.error('error');
    }));

    it('should only log an error when the log level is ERROR', inject(function($log) {
        expect($log.log.logs.length).toBe(0);
        expect($log.debug.logs.length).toBe(0);
        expect($log.info.logs.length).toBe(0);
        expect($log.warn.logs.length).toBe(0);
        expect($log.error.logs.length).toBe(1);
    }));

    it('should log an error and warn when the log level is WARN', inject(function($log) {
        expect($log.log.logs.length).toBe(0);
        expect($log.debug.logs.length).toBe(0);
        expect($log.info.logs.length).toBe(0);
        expect($log.warn.logs.length).toBe(1);
        expect($log.error.logs.length).toBe(1);
    }));

    it('should log an error, warn and info when the log level is INFO', inject(function($log) {
        expect($log.log.logs.length).toBe(0);
        expect($log.debug.logs.length).toBe(0);
        expect($log.info.logs.length).toBe(1);
        expect($log.warn.logs.length).toBe(1);
        expect($log.error.logs.length).toBe(1);
    }));

    it('should log an error, warn, info and debug when the log level is DEBUG', inject(function($log) {
        expect($log.log.logs.length).toBe(0);
        expect($log.debug.logs.length).toBe(1);
        expect($log.info.logs.length).toBe(1);
        expect($log.warn.logs.length).toBe(1);
        expect($log.error.logs.length).toBe(1);
    }));

    it('should log an error, warn, info, debug and info when the log level is LOG', inject(function($log) {
        expect($log.log.logs.length).toBe(1);
        expect($log.debug.logs.length).toBe(1);
        expect($log.info.logs.length).toBe(1);
        expect($log.warn.logs.length).toBe(1);
        expect($log.error.logs.length).toBe(1);
    }));

});

});

我只需要弄清楚如何在每次测试开始时设置currentLogLevel然后我就完成了。再一次,任何想法?

最终更新:我设法为每个测试用例配置一个新的LOG_LEVEL常量。

    function attemptToLog( requestLevel, msg ) {
        if ( LOG_LEVEL.CURRENT_LOG_LEVEL >= LOG_LEVEL[requestLevel] ) {
        ...
    }

....

mockLogLevel = {
    OFF:    0,
    ERROR: 20,
    WARN:  30,
    INFO:  40,
    DEBUG: 50,
    LOG:   60,
    ALL:  100,
    CURRENT_LOG_LEVEL: 100
};

...

describe('logging when the level is set to ERROR', function() {

    beforeEach(module(function ($provide) {
        mockLogLevel.CURRENT_LOG_LEVEL = mockLogLevel.ERROR;
        $provide.constant('LOG_LEVEL', mockLogLevel);
    }));

    beforeEach(inject(function ($log) {
        logEverything($log);
    }));

    it('should log error only', inject(function($log) {
        expect($log.log.logs.length).toBe(0);
        expect($log.debug.logs.length).toBe(0);
        expect($log.info.logs.length).toBe(0);
        expect($log.warn.logs.length).toBe(0);
        expect($log.error.logs.length).toBe(1);
    }));
});

....

function logEverything($log) {
    $log.log('log');
    $log.debug('debug');
    $log.info('info');
    $log.warn('warn');
    $log.error('error');
}

0 个答案:

没有答案