Check out myAngular article series with live demos and Facebook group Angular - Advanced Topics

How to unit test Angular run blocks

Torgeir "Tor" Helgevold
- JavaScript Developer and Blogger
Published: Sun May 10 2015

Run blocks in Angular are commonly used to bootstrap the application and run initial setup functions. In some cases the logic might be complex enough to warrant unit tests, so in the following post, I will demonstrate how to capture run block(s) from a unit test.

Below is an example of two different run blocks wired up to the same Angular application.

angular.module('app').run(['applicationReadyService',function(applicationReadyService){
    applicationReadyService.done(1);
}]);
angular.module('app').run(['applicationReadyService',function(applicationReadyService){
    applicationReadyService.done(3);
}]);

The trick to testing this is to grab the callback functions of the run blocks and run them as regular methods in the test. It turns out that Angular exposes these callback through a private _runBlocks array.

The callback can then be indexed directly in the array as the last item in the captured run block as shown in the code below.

describe('run module test', function(){
    it('should call done methods in module', function(){
        var myModule = angular.module('app');
        
        var firstRunBlockCallback = myModule._runBlocks[0][myModule._runBlocks[0].length - 1];
        var secondRunBlockCallBack = myModule._runBlocks[1][myModule._runBlocks[1].length - 1];
        var applicationReadyServiceMock = {done:function(){}};
        
        spyOn(applicationReadyServiceMock,'done');
        
        firstRunBlockCallback(applicationReadyServiceMock);
        expect(applicationReadyServiceMock.done).toHaveBeenCalledWith(1);
        
        secondRunBlockCallBack(applicationReadyServiceMock);
        expect(applicationReadyServiceMock.done).toHaveBeenCalledWith(3);
    });
});

The example might almost be too trivial in this case, but the functionality is intentionally kept simple in order to illustrate how the test can gain access to the seemingly closed off run blocks.

I have added a couple of simple expects to detect that the done method of the applicationReadyService was called with the appropriate parameter.

If you liked this article, share it with your friends on social media:

We also have a new Facebook group about advanced Angular topics.

I invite you to follow me on twitter