Tuesday, January 27, 2015

Unit Testing AngularJS with Mocked Services

Overview:
Recently, I have been playing around with Javascript and AngularJS. Predominantly, being a backend developer, this was a good challenge.
And prior I had no extensive experience on Javascript nor AngularJS. So, I am a newbie.

However, I thought to blog some of my learnings, specially when it comes to testing the code.

This tutorial only touches the basic essence of mocking certain Javascript codes when unit testing.

The sample code for this project can be found here.

Prerequisites 

- NodeJS installed. You can find out more at http://nodejs.org/
- Git

Step 1: Cloning the project

$ git clone https://github.com/fazlan/angularjs.git

Step 2: Moving to the sample folder

$ cd angularjs/angular-mock-service-sample

Step 3: Installing required node dependencies


{
   "name": "mock-service",
   "version": "1.0.0",
   "description": "",
   "author": "",
   "license": "ISC",
   "devDependencies": {
      "jasmine-core": "^2.1.3",
      "karma": "^0.12.31",
      "karma-jasmine": "^0.3.5",
      "karma-phantomjs-launcher": "^0.1.4",
      "phantomjs": "^1.9.13"
   }
}
 
$ npm install -g karma-cli  

The above is optional. You can skip the above if you have already installed karma-cli globally

$ npm install       

This will install all the node dependencies in the package.json

Step 4: Installing required bower dependencies
 
{
   "name": "mock-service",
   "version": "0.0.0",
   "license": "MIT",
   "devDependencies": {
      "angular": "~1.3.11",
      "angular-mocks": "~1.3.11",
      "angular-loader": "~1.3.11"
   }
}

$ npm install -g bower 

The above is optional. You can skip the above if you have already installed bower globally

$ bower install       

This will install all the bower dependencies in the bower.json

Step 5: Karma configuration


// Karma configuration
// Generated on Tue Jan 27 2015 14:23:24 GMT+1100 (Tasmania Daylight Time)

module.exports = function(config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',


    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine'],


    // list of files / patterns to load in the browser
    files: [
        'bower_components/angular/angular.js',
        'bower_components/angular-route/angular-route.js',
        'bower_components/angular-mocks/angular-mocks.js',
        'app/src/**/*.js',
        'app/test/**/*_spec.js'
    ],


    // list of files to exclude
    exclude: [
    ],


    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
    },


    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress'],


    // web server port
    port: 9876,


    // enable / disable colors in the output (reporters and logs)
    colors: true,


    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,


    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: false,


    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['PhantomJS'],


    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: true
  });
};


Step 6: Jasmine test with mocks


'use strict';
describe('The Mocked User Controller', function () {
    var scope;

    beforeEach(function () {

        // load the module
        module('user.module', function ($provide) {
            // mock the angular service
            var mockedUserService = {};
            mockedUserService.getUsers = function () {
                return ['user1', 'user2'];
            };
            // inject the mocked angular services
            $provide.value('UserService', mockedUserService);
        });

        // inject the angular services
        inject(function ($controller, $rootScope) {
            scope = $rootScope.$new();
            $controller('UserController', {$scope: scope});
        });
    });

    it('Returns the list of users', function () {
        expect(scope.users).toContain('user1', 'user2');
    });
});


Step 7: Running the Jasmine tests
 
$ karma start karma.config.js
 
You'll see all your tests being run and their results.

Summary:
In this article, we looked at how to test Javascript code using Jasmine. You can find the sample code for this post here.

No comments:

Post a Comment