Logging / debugging is often used in unit tests and that is no exception when working with AngularJS. In Angular we mostly use $log.debug (or $log.whatever), however in unit tests $log.debug doesn’t work and we’re forced to use javascript’s console.log. $log.debug is actually just AngularJS’ wrapper around this.

And then we often fill our tests and the source code with $log.debug‘s and feel compelled to comment all these out.

Outside of unit tests we can use the $logProvider to turn off debugs:


angular.module('app', [])
	.config(['$logProvider', function($logProvider){
		$logProvider.debugEnabled(false);
	}])

But this has no affect on console.log.

My requirements were:

  • Use $log.debug in my unit tests
  • Be able to turn logging (debug) on and off in my unit test (irrespective of $logProvider)

And this is how I did it (this using Jasmine for unit testing).


	describe('tooltipService', function () {
		// Set up logging
		var $log;
		var mockLog = {debug:function(){}}; // turn local logging off
		// var mockLog = {debug:console.log}; // turn local logging on

		...

		beforeEach(module(function ($provide) {
			mockResourceService = {getTooltips: jasmineNG.createPromiseReturningSpy(sampleTooltips)};
			$provide.value('resourceService', mockResourceService);
			$provide.value('$log', mockLog);
		}));

		beforeEach(inject(function ($rootScope, $q,_$log_, tooltipsService) {
			$log=_$log_;
			...

It may be nice to be able to set this globally for all tests in a project and override locally but haven’t yet tried that.

Now I can use $log.debug in my unit tests and can easily turn off ALL LOGGING by reversing the commented-out lines. Ie. changing the above lines to:


		// var mockLog = {debug:function(){}}; // turn local logging off
		var mockLog = {debug:console.log}; // turn local logging on

Also as an added bonus in this blog post, notice the mockResourceService and in particular the jasmineNG. This is part of a brilliant and clean way for testing services called by services and which return promises (as they should). I found this at http://decodify.blogspot.com.au/2013/10/angularjs-unit-testing-helper-for.html. For your reading pleasure the test setup and the first test that uses this is included below for your reading pleasure:


'use strict';

describe('tooltipService', function () {
    // Set up logging
    var $log;
    var mockLog = {debug:function(){}};         // turn local logging off
//    var mockLog = {debug:console.log};        // turn local logging on

    var mockResourceService;
    var jasmineNG = {};
    var scope;
    var service;
    var sampleTooltips = {
        'common': {'Global Unique ID': 'Globally unique identifier for the borehole (eg. a URI like http://pir.sa.gov.au/borehole/AZW74652526'},
        'petroleum': {'hydrocarbons': 'The summary of hydrocarbons encountered in the well'}
    };

    //set $q in your test
    jasmineNG.$q = undefined;
    jasmineNG.createPromiseReturningSpy = function (retval) {
        return jasmine.createSpy().andCallFake(function () {
            var res = jasmineNG.$q.defer();
            res.resolve(retval);
            return res.promise;
        });
    };

    beforeEach(module('gaBh.Module.App.dataService.tooltipsService'));

    // Mock service
    beforeEach(module(function ($provide) {
        mockResourceService = {getTooltips: jasmineNG.createPromiseReturningSpy(sampleTooltips)};
        $provide.value('resourceService', mockResourceService);
        $provide.value('$log', mockLog);
    }));

    beforeEach(inject(function ($rootScope, $q,_$log_, tooltipsService) {
        $log=_$log_;
        jasmineNG.$q = $q;
        scope = $rootScope.$new();
        service = tooltipsService;
    }));

    describe('getTooltip', function () {
        it('"common, global Unique ID" should return "Globally unique identifier for the borehole ..."', function () {
            var expected = 'Globally unique identifier for the borehole';
            var section = 'common';
            var elements = ['Global Unique ID'];
            var theData = '';
            $log.debug('this is debug');
            service.getTooltip(section, elements).then(function (data) {
                theData = data;
            }, function (error) {
                $log.debug('ERROR - ', error);
            });
            // force the promise to resolve
            scope.$apply();
            expect(theData).toContain(expected);
        });

Comments are closed.

Brooke Smith is proudly powered by WordPress and the Theme Adventure by Eric Schwarz
Entries (RSS) and Comments (RSS).

Brooke Smith

Portfolio and site of a software engineer