Getting started with Unit Testing in {{AngularJS}} – Part 19

Unit Testing one of the important activities in software development. It helps in reducing the number of bugs in the code and maintaining the code quality. As now a days we work on small releases and keep adding/updating features, Unit Test plays a vital role in maintaining the quality and helps in making sure that new changes does not break earlier functionality and reduces the testing effort. Unit Test becomes more important for languages like JavaScript because it is loosely typed and we don’t find issues until we run the functionality. Also testing and debugging JavaScript is another time consuming activity.

Note – This post is a part of series of posts on AngularJS and it is 19th one. Click here to view all the post. Apart from that you can also use the navigation links for next and previous post in each post at the bottom to check all.

What is Unit Testing

Unit Test is a snippet of code or function which tests a unit of code (function/API) and all the required dependencies are mocked. It means it just test the business logic written in the function and if any other dependent instance is required then mocked version is used. Unit test does not call any real service, database call etc.

What do we need in AngularJS to get started

Being a .NET developer, I have written thousands of unit tests using C# and Visual Studio. You might be knowing that to create and run an unit test, we require unit test framework where we can run our unit test (like NUnit, MSTest etc), Unit test APIs , Mocking framework  (like NMock, Rhino mock) and then these tests can be part of Continuous Integration system where we can run the unit tests on every check-in to the repository. Similar infrastructure set up we also need in AngularJS. There are many options but I am going to use the most recommended one’s. Let’s discuss all

  1. Jasmine – It is a behavior driven development framework for testing JavaScript code and preferred for Angular Applications. There are similar others like Qunit that we can use.
  2. Angular- mock – Angular provides its own mocking framework which helps in mocking the dependent objects.
  3. Test Runner –  One of the most used Test-runner in Karma but as we are fond of using Visual Studio, there is another nice test runner called Chutzpah which provides a plugin (Chutzpah Test Adapter) for Visual Studio which is very useful.

We have discussed the required tools. Now let’s set up our environment as

  1. Create a ASP.NET Project (I am starting with empty ASP.NET MVC Project with Unit Tests).
  2. Install Chutzpah Test Adapter plugin via Nuget manager
    chutzpah
  3. Install Jasmine Nuget package.
    Jasmine
  4. Add Angular mock (angular-mocks.js) library for mocking purposes.

Now we have set up our solution. First we will write a simple (addition) method and a unit test to verify the set up. Before writing test let’s understand the following three items which are minimum to write any unit test using Jasmine.

  1. describe – This is a global function that takes string and function as parameter which represents a suite of test. In another way, it provides us a way to group multiple tests.
  2. it – This is another function which is written inside global function and takes two parameter as above string and function and this function is actual test.
  3. expect – It takes the function that need to be tested as parameter and provide a list of matchers to match the result.

Let’s write a JavaScript  function and write unit test for that as

  1. Add a folder in scripts folder (say CustomAngular) and add new JavaScript file say Home.js .
  2. Write a Add function in the Home.js as
    function Add(firstnum, secondnum) {
        return firstnum + secondnum;
    }
    
  3. Add a file Home.test.js in scripts folder of Unit Test project to write our unit tests cases.
  4. It’s time to write our unit test for the same as
    describe("My First Test -> ", function () {
        it("Add with two positive num", function() {
            expect(Add(2, 3)).toEqual(5);
        });
    });
    

So we have written our first test. I already explained the special key words used here. You also need to include the references of Jasmine library and Home.js here. To run this Unit test, we just need to build the solution and open the Test Explorer and run the Unit Test. After running the Unit Test it will show green as

TestExPSampleIt means we have set up our infrastructure correctly. So let’s move to real stuff. First we will create a MVC sample application then write unit test. This application would be similar to which we have created in our series of post. But we will take small steps to understand it better. Our MVC application looks as

ExampleLet’s see code quickly. Our MVC controller (HomeController) has just one Index method which returns a view. Our Index View is as


<h2>Talk Details</h2>


<div class="container">

<div class="row" ng-controller="talkController">

<table class="table table-bordered table-condensed table-hover">

<tr ng-repeat="talk in talks">

<td> {{talk.id}}</td>


<td> {{talk.name}}</td>


<td> {{talk.speaker}}</td>


<td> {{talk.venue}}</td>


<td> {{talk.duration}}</td>

 </tr>

 </table>

 </div>

 </div>

Now let’s see our JavaScript file where we have put up our Angular code

var homeModule = angular.module("homeModule", []);

homeModule.controller("talkController", ['$scope', function ($scope) {

    $scope.talks =  [
        { id: '1001', name: 'Real Time Web Applications with SignalR', speaker: 'Brij Bhushan Mishra', venue: 'Hall 1', duration: '45' },
        { id: '1002', name: 'Power of Node.js', speaker: 'Dhananjay Kumar', venue: 'Hall 2', duration: '75' },
        { id: '1003', name: 'Getting started with AngularJS', speaker: 'Brij Bhushan Mishra', venue: 'Hall 1', duration: '60' },
        { id: '1004', name: 'Microsoft Azure - Your cloud destination', speaker: 'Gaurav mantri', venue: 'Hall 1', duration: '45' }
      ];

}]);

Also I have included Angular library, Home.js and added ng-app attribute as well. Now we will write the unit test for our Angular Controller.

First let’s understand our Angular controller. Here We have a module and a controller which takes one parameter $scope. So while writing test, we require these three items and these need to be initialized first before running the test. To initialize, Jasmine provides us beforeEach function which can be used to initialize the items which runs before the test. And we need Angular mock library to set up all. Let’s see the test and then discuss each

describe("Talk Controller Tests -> ", function () {
    var scope;
    var $ctrlCreator;

    beforeEach(module("homeModule"));
    beforeEach(inject(function ($controller, $rootScope) {
        $ctrlCreator = $controller;
        scope = $rootScope.$new();
    }));


    it("It should have four talks", function () {
        $ctrlCreator("talkController", { $scope: scope });

        expect(scope.talks.length).toBe(4);
    });

});

In the above code snippet, we first created two variables then initialized homeModule after that we injected controller and scope instance with the help of mock. In our Test, we are testing that length of talks returned by our controller is four. Now we can run our unit test via Test Explorer and it will pass. Similarly we can write many more tested for controller’s functions.

Conclusion

In this post, we talked about Unit test in angular. What are the basic things required to set up the project and get it started. Then we created a simple function Add and wrote unit test for that to check the setup. We continued writing the unit test of our controller and saw that how to initialized items before running the test. Hope you have enjoyed the post. In next Post we will continue talking about Unit Testing and write unit tests for some other components.

Cheers,
Brij

Advertisement