DotNetCurry Logo

Unit Testing AngularJS Controllers using Karma and Jasmine

Posted by: Mahesh Sabnis , on 2/2/2016, in Category AngularJS
Views: 17752
Abstract: Unit testing Angular Controllers using Jasmine and Karma without requiring DOM.

Unit testing is an important step in the software development process which makes sure that every unit of code in all layers of the application is tested successfully.

Angular.js is a widely used client-side MVC framework in modern applications. Since this framework provides separating of client-side components using inbuilt dependency injection, it also brings with it support for testing every component e.g. Angular Controller, Angular Service etc. It’s always a good practice to test client-side components before deployment.

 

In this article, we will unit test an Angular Controller. Here are some of the frameworks that can be used for testing AngularJS applications.

Jasmine - a behavior-driven development framework for testing JavaScript code. A major feature of this framework is that it does not depend on any JavaScript framework and neither does it need DOM to test the code. This provides clean syntax using which we can write tests. It also provides functions for structuring the test using assertions. More information about Jasmine can be read from this link.

Protractor - an end-to-end testing framework for Angular.js applications. This framework runs tests against the application running in a real browser. This is a Node.js program and uses Jasmine for its test syntax. More information about Protractor can be read from here and here .

Karma - is a JavaScript command line tool. This tool uses the web server to load the application code and test it. This tool runs on Node.js and is available as a NPM package. More information about this tool can be read from this link.

Unit testing AngularJS Controllers using Jasmine

In this article, we will use Jasmine framework for testing our AngularJS controller.

We will use the free community edition of Visual Studio 2015 although you can use any other free Editor like Sublime Text, Visual Studio Code etc.

Prerequisites: You must already have Node.js installed on your system.

Step 1: Open Visual Studio and create a new ASP.NET Empty Web Application of name e.g. NG_CtrlTestApp. In this project, using NuGet Package Manager install AngularJS. Right click on the project and select option Manage NuGet Packages. Search for AngularJS from the search Text Box of the NuGet Package Manager window as shown in the following image:

angularjs-package

Make sure that the suitable AngularJS framework is selected. Once the installation is over, the project will be added with the Scripts folder with angular scripts in it. We need angular.min.js and angular-mocks.js as shown in the following image:

angular-mock-references

Angular-mocks is an ngMock module. This module provides mocking for our tests. Mocking is primarily used in Unit testing to create objects that simulate the behavior of real objects. This module injects and mocks the angular service inside the unit tests.

Step 2: In the project, add a new folder of name ‘MyScripts’. In this folder add the following JavaScript file

app.js

//1.
var app = app = angular.module('appmodule', []);
//2.
app.controller('mycontroller', function ($scope) {
    $scope.Employee = {
        EmpNo: 0,
        EmpName: "",
    };
    //3.
    $scope.Employee.EmpName = 'MS';

    //4.
    $scope.lower = function (ename) {
        return ename.toLowerCase(); 
    };
     
});

The above script code is very simple. The line numbers below matches with comments in above JavaScript code.

1. Define angular module of name appmodule.

2. Define angular controller of name mycontroller with scope employee object.

3. The EmpName of Employee object is initialized.

4. The scope() function is used to convert the EmpName on lowercase.

Testing the AngularJS Controller

Step 3: In this project we will add the Jasmine NuGet package. Follow same instructions as of Step 1 for AngularJS package.

jasmine-test-package

This step will add the following contents in the project:

  • Jasmine sub-folder in the Content folder with jasmine stylesheets in it.
  • Controllers folder with JasmineController.cs class in it.
  • Jasmine sub-folder in the Scripts folder with Jasmine Framework Scripts.
  • Jasmine-samples sub-folder in the Scripts folder providing some sample test scripts.
  • Views folder with Jasmine sub-folder in it. This contains the SpecRunner.cshtml in it which is a View file containing sample scripts references. We will change this file shortly.

Step 4: In the project add a new folder of name Test. In this folder add SpecRunner.cshtml by renaming it to SpecRunner.html and a JavaScript file of name controllertest.js

Step 5: In controllertest.js, add the following code

//1.
describe('mycontroller', function () {
    //2.
    beforeEach(module('appmodule'));
    //3.
    it('scopeTestSpec',
        //4.
        inject(function ($controller, $rootScope) {
            var $scope = $rootScope.$new();
            $controller('mycontroller', {
                $scope: $scope
            });
            //5.
            expect($scope.Employee.EmpName).toEqual('MS');
           
        }));
            //6.
it('scopeTestSpecFunction',
        inject(function ($controller, $rootScope) {
            var $scope = $rootScope.$new();
            $controller('mycontroller', {
                $scope: $scope
            });
            expect($scope.lower('MAHESH')).toEqual('mahesh');
        }));
});

The above script code has the following specifications. (Note: Following line numbers matches with comments applied in above JavaScript code.)

1. ‘describe’ defines what is it testing. In our case, it is a controller name passed to it.

2. ‘beforeEach’ allows to execute some code before each test spec. In our case, it is executing the angular module.

3. The spec is defined by calling the function ‘it’. The first parameter for this function is string which is title of spec. The second parameter is the spec itself.

4. The second parameter of ‘it’ contains one or more expectations for our test. In our case, it injects controller and scope and receives an instance of scope using $new for the controller $controller.

5. The ‘expect’ in scopeTestSpec defines the test for EmpName.

6. The ‘expect’ in scopeTestSpecFunction defines the test for lower() function.

 

Using Karma to Run Test in AngularJS

Step 6: Open Node.js command prompt and navigate to the project folder.

npm install jasmine-core

npm install karma karma-jasmine karma-chrome-launcher --save-dev

This will install necessary karma plug in for the current project.

Run the following command to install the karma cli

npm install -g karma-cli

Run the following command from the command prompt to initialize karma

karma init

This step will ask you for the Testing environment settings.

The following needs to be selected:

· Testing Framework: Jasmine

· Require.js: no

· Capture any browser automatically : chrome (Press Enter twice)

· Location of Source and test files: press Enter

· Should any files included by the previous pattern to be excluded: press Enter

· Do you want Karma to Watch all the files and run the tests on change: Yes

These steps will generate karma.conf.js.

(Note: By default this file will be hidden in Visual Studio. So click on show all file option in Solution Explorer window and include the file in the project by right clicking on the file.)

Step 7: Make the following changes in the ‘files’ array of karma.conf.js

files: [
    "Scripts/angular.js",
    "Scripts/angular-mocks.js",
    "MyScripts/app.js",
    "Test/controllertest.js"
],

This will specify files to be loaded during test.

Step 8: Add following script references in the SpecRunner.html.

http://../../Scripts/angular.min.js
http://../../Scripts/angular-mocks.js
http://../../MyScripts/app.js
http://../../Test/controllertest.js

Step 9: Run the following command from the command prompt to run the test

karma start karma.conf.js 

This will start the Chrome browser and the test results will be shown in the Command window as shown in the following image

success-result

The above image shows both test are successful.

Press Ctrl+C to terminate the Test.

Failing the Tests

Make changes in the function() test as shown in following code:

expect($scope.lower('MAHESH')).toEqual('maheshSSSS');

Here we have changed expect() for lower function and pass a resultant value that is nor equal so as the test to fail. Run the test again and as expected, the second test will fail as shown in the following image:

failed-test

It shows the first test 1 of 2 is successful and 2 of 2 failed with the required description.

Conclusion:

Jasmine with Karma provides a command line utility to unit test the Angular Controller without requiring DOM.

Download the entire source code of this article (Github)

Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+
Further Reading - Articles You May Like!
Author
Mahesh Sabnis is a DotNetCurry author and Microsoft MVP having over 17 years of experience in IT education and development. He is a Microsoft Certified Trainer (MCT) since 2005 and has conducted various Corporate Training programs for .NET Technologies (all versions). Follow him on twitter @maheshdotnet


Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!