Showing posts with label Unit Testing. Show all posts
Showing posts with label Unit Testing. Show all posts

Saturday, 13 June 2015

Everything You Need to Know to Unit Test AngularJS Code

Unit testing is one of the crucial and necessary parts of software development. This phase improves the quality of product, assures accuracy in behavior and also reduces the cost involved in fixing the bugs. There are some good advantages for a developer writing unit tests as well.

AngularJS is one of the most popular framework for building Single Page Applications. One of the key reasons behind its success is, testability. Every piece of code written in AngularJS is unit testable. The features like Dependency Injection make the code written on the framework easier to test.

In the past, I wrote a few posts on unit testing AngularJS controller using Jasmine and QUnit and I also covered a few tips. Over past two years, I worked a lot on AngularJS and thus I wrote a lot of code and tests. This process taught me a lot of tips on unit testing AngularJS code that I wanted to share with the community. As some of you might be aware that I am a regular author for SitePoint, I have put together a series of four articles covering tips on mocking and testing almost every block in AngularJS. Following are the links to these articles:


  1. Mocking Dependencies in AngularJS Tests
  2. Unit Testing in AngularJS: Services, Controllers & Providers
  3. AngularJS Testing Tips: Testing Directives
  4. AngularJS Testing: Bootstrap Blocks, Routes, Events, and Animations


The process of putting these articles together has not been easy for me and at the same time, I enjoyed a lot while writing them. Read them when you get time and feel free to drop any feedback to me.

Happy coding!

Sunday, 28 September 2014

Unit Testing Config and Run Blocks in AngularJS

One of the best-selling points of AngularJS framework is testability. Any piece of code written in an AngularJS application is testable unless it is corrupted by a global object.

All of the blocks in AngularJS except config and run blocks can be instantiated or invoked and tested. Config and run blocks are executed as soon as the module containing the block is loaded into memory. There is no way to call them manually; unless the bodies of these blocks are defined independently and then hooked to a module. But, they are invoked automatically when the module is loaded. So, I don’t see a need to invoke them manually to test their logic.

Say, we have the following module with a config block registering routes and a run block that listens to a global message event to the window:



var app = angular.module('testApp',['ngRoute']);

app.config(function($routeProvider){
  $routeProvider.when('/', {templateUrl:'templates/home.html',controller:'homeCtrl'})
    //definitions of other routes
    .otherwise({redirectTo:'/'});
});

app.run(function($window, $rootScope){
  $window.addEventListener('message', function(event){
    $rootScope.$broadcast(event.data);
  });
});


In test of the config block, we need to see if the methods when and otherwise are called with right parameters. To do that, we must spy these methods and store a reference of $routeProvider as soon as the module in loaded in tests. Providers cannot be mocked using $provide like services as they are not available after config phase. We can pass a callback to module loader and create spies on the methods whose calls have to be inspected.

Following snippet shows how to spy on a provider’s method and a test that checks if the method is called:


describe('testing config block', function() {
  var mockRouteProvider;

  beforeEach(function () {
    module('ngRoute', function ($routeProvider) {
      mockRouteProvider = $routeProvider;
      spyOn(mockRouteProvider, 'when').andCallThrough();
      spyOn(mockRouteProvider, 'otherwise').andCallThrough();
    });
    module('testApp');
  });

  it('should have registered a route for \'/\'', function(){
    expect(mockRouteProvider.when).toHaveBeenCalled();
  });
});


If you run the above test now, it should fail. That’s strange, isn’t it?

I spent a lot of time struggling with it and found two approaches to make the above test pass.

One approach is to have a dummy test before the test that performs an assertion on the logic of config block. You can leave this test empty as it doesn’t have to do anything, or have an assertion that would always pass.


it('doesn\'t have any assertions', function(){});


I didn’t like this approach; as it adds a test that would always pass and doesn’t carry any value. The other approach to make the above test pass is by calling inject() inside a beforeEach block. The inject function is generally used to get references of services that are needed in the tests. Even if there is no need of any service in the tests, the inject block can be called without any callback to bootstrap the modules already loaded using module() blocks.

beforeEach(function(){
  inject();
});


You will see the same issue with run() block as well. It isn’t executed unless a test is executed or inject block is executed.

If you got a better approach to bootstrap modules in tests, feel free to post a comment.

Happy coding!

Sunday, 30 March 2014

Basics: Benefits of Writing Unit Tests

Quite often people ask the reasons of writing unit tests for their code. There are several benefits of writing unit tests that add value to the code as well as the developers writing the tests. I am listing a set of points here that came to my mind while thinking about the benefits of Unit testing.

Benefits to code:
  • The code will have very few bugs as most of them are identified and resolved while running tests
  • Silly mistakes are inevitable while writing code. Identifying them while running the application is difficult at times. Unit tests catch them instantly
  • Code doesn’t need documentation. Names of the behaviours or methods defined in unit tests shout the purpose of their part
  • Testable code is easily extensible too. Adding new features to the code becomes easy
  • If Unit tests are written right from beginning of development, the underlying code automatically follows a set of quality measures that are otherwise very difficult to achieve
  • After applying some modifications, the code can be shipped within very less amount of time, as most of the regression testing is also done by the unit tests


Benefits to Programmers:
  • Unit testing teaches good programing practices to developers
  • Unit tests force programmers to use some of the features of the language and framework that would otherwise remain just as theories in programmers’ minds
  • As we write more code, our thinking about code starts maturing. With unit tests, we are bound to write a lot of additional code than the usual production code. So, it improves the programmer’s ability to think logically
  • Programmers gain the experience of writing clean, loosely coupled code and learn the ways to avoid anti-patterns
  • It becomes very easy for any new member to understand and start working on the code


These are just my opinions. The list is definitely not limited to the above set of points. Feel free to put a comment on anything that I didn’t mention in the above list.

Happy coding!

Tuesday, 31 December 2013

Triggering Events in Angular JS Directive Tests

The best place to perform DOM manipulations in an Angular JS application is in a directive. Sometimes we handle events on the elements wrapped inside the directive to perform required action. The jQlite implementation in Angular JS provides enough APIs to handle these events in the body of the directives. We can use jQuery as well, if API exposed by jQlite is not enough.

One of the primary design goals of Angular JS is testability. Directives are testable too. Since we work directly on DOM with directives, testing becomes a bit tricky. One of such trickier part to test is event. Say, we have a directive that handles blur event on a text box:

app.directive('textBoxBlur', function($window){
  return{
    require:'ngModel',
    link: function(scope, element, attrs, ngModel){
      element.bind('blur', function(e){
        $window.alert("value entered: " + element.val());
      });
    }
  }
});

To call the DOM events manually, jQlite provides a handy method triggerHandler. It is similar to jQuery’s triggerHandler method. It can be fired using jQlite object of any element. Following statement shows this:
elem.triggerHandler('blur');

Since we have to do it repeatedly in tests, it is better to wrap it inside a reusable function as shown below:
changeInputValue = function (elem, value) {
    elem.val(value);
    elem.triggerHandler('blur');
};

Now the above function can be called from any test case to test behaviour of the blur event.
it('Should call alert on losing focus', function(){
  changeInputValue(form.find('input'), "Ravi");
  expect(windowMock.alert).toHaveBeenCalled();
});

Complete sample is available on plnkr: http://plnkr.co/edit/InkyGdIhZiwfe0NC4hyu?p=preview

Happy coding!

Sunday, 22 December 2013

Mocking promises in Angular JS Controller Tests

In a typical Angular JS application, we wrap the calls to backend services in a custom Angular JS service and return a promise from the method in the service to the calling component. For instance, say the calling component is a controller. While testing the controller, we create a mocked service instance with methods replaced by spies. As the original method in the service returns a promise containing the result from executing the backend API, the spy should return a mocked promise with a dummy result.

A few months back, when I was learning Angular and blogging my learning, I did blog posts on unit testing controllers using Jasmine and also on unit testing controllers using QUnit. Back then, I used to use spyOn().andCallThrough() on all methods in the service and used $httpBackend to avoid calling the backend APIs from the service. With time, I understood that this approach is not good as the controller still depends on the logic written inside the service. In this post, we will see how to return mock promises from the spies to isolate controller from the service.

Following are the service and the controller we will be using in this post:

var app = angular.module("myApp", []);
app.factory('dataSvc', function($http, $q){
    var basePath="api/books";
    getAllBooks = function(){
        var deferred = $q.defer();
 $http.get(basePath).success(function(data){
            deferred.resolve(data);
        }).error(function(err){
          deferred.reject("service failed!");
        });
        return deferred.promise;
     };
  
     return{
         getAllBooks:getAllBooks
     };
});

app.controller('HomeController', function($scope, $window, dataSvc){
   function initialize(){
       dataSvc.getAllBooks().then(function(data){
           $scope.books = data;
       }, function(msg){
          $window.alert(msg);
       });
   }

  initialize();
});

Let’s create a spy for the service. This is a bit tricky, as we need to force the promise to pass or fail based on a condition. At the same time, it is simple as $q provides the ready methods when and reject to make our job easier. Following is the spy for getAllBooks method:
var succeedPromise;
spyOn(booksDataSvc, "getAllBooks")
    .andCallFake(function(){
        if (succeedPromise) {
            return $q.when(booksData);
        }
        else{
            return $q.reject("Something went wrong");
        }
    });

The fake implementation of getAllBooks passes if value of the field succeedPromise is set to true, otherwise it fails. We need to manipulate this field in the test cases.

In the test cases, we need to call scope.$digest before checking the expectations, as the promise is triggered from a spy method, which is in non-angular world.

Following test case checks if the books object is set to some value when the promise passes.

it('Should call getAllBooks on creating controller', function(){
    succeedPromise = true;
    createController();
    homeCtrlScope.$digest();
    expect(booksDataSvc.getAllBooks).toHaveBeenCalled();
    expect(homeCtrlScope.books.length).not.toBe(0);
  });

The promise can be forced to fail by just setting succeedPromise to false in the test case. Following test case demonstrates it:
it('Should alert a message when service fails', function(){
    succeedPromise = false;
    createController();
    homeCtrlScope.$digest();
    expect(booksDataSvc.getAllBooks).toHaveBeenCalled();
    expect(windowMock.msg).not.toBe("");
  });

The complete sample is available on plnkr: http://plnkr.co/edit/xD9IPb6TRduAUwRGbIIG

Happy coding!

Wednesday, 18 December 2013

Unit Testing Asynchronous Web API Action Methods Using MS Test

Since Entity Framework now has a very nice support of performing all its actions asynchronously, the methods in the repositories in our projects will turn into asynchronous methods soon and so will be the code depending on it. Tom Fitzmacken did a nice job by putting together a tutorial on unit testing Web API 2 Controllers on official ASP.NET site. The tutorial discusses on testing synchronous action methods. The same techniques can be applied to test asynchronous action actions as well. In this post, we will see how easy it is to test asynchronous Web API action methods using MS Test.

I created a simple repository interface with just one method in it. The implementation class uses Entity Framework to get a list of contacts from the database.

public interface IRepository
{
    Task<IEnumerable<Contact>> GetAllContactsAsync();
}

public class Repository : IRepository
{
    ContactsContext context = new ContactsContext();

    public async Task<IEnumerable<Contact>> GetAllContactsAsync()
    {
        return await context.Contacts.ToArrayAsync();
    }
}

Following is the ASP.NET Web API controller that uses the above repository:
public class ContactsController : ApiController
{
    IRepository repository;

    public ContactsController() : this(new Repository())
    { }

    public ContactsController(IRepository _repository)
    {
        repository = _repository;
    }

    [Route("api/contacts/plain")]
    public async Task<IEnumerable<Contact>> GetContactsListAsync()
    {
        IEnumerable<Contact> contacts;
         try
         {
            contacts = await repository.GetAllContactsAsync();
         }
         catch (Exception)
         {
             throw;
         }
           
         return contacts;
    }

    [Route("api/contacts/httpresult")]
    public async Task<IHttpActionResult> GetContactsHttpActionResultAsync()
    {
        IEnumerable<Contact> contacts;

        try
        {
            contacts = await repository.GetAllContactsAsync();
        }
        catch (Exception ex)
        {
            return InternalServerError(ex);
        }
        
        return Ok(contacts);
    }
}

As we see, the controller has two action methods performing the same task, but  the way they return the results is different. Since both of the action methods respond to HTTP GET method, I used attribute routing to distinguish them. I used poor man’s dependency injection to instantiate the repository; it can be easily replaced using an IoC container.

Before writing unit tests for the above action methods, we need to create a mock repository.

public class MockRepository:IRepository
{
    List<Contact> contacts;

    public bool FailGet { get; set; }

    public MockRepository()
    {
        contacts = new List<Contact>() {
            new Contact(){Id=1, Title="Title1", PhoneNumber="1992637281", CustomerId=1},
            new Contact(){Id=2, Title="Title2", PhoneNumber="9172735171", SupplierId=2},
            new Contact(){Id=3, Title="Title3", PhoneNumber="8361910353", CustomerId=2},
            new Contact(){Id=4, Title="Title4", PhoneNumber="7801274518", SupplierId=3}
        };
    }

    public async Task<IEnumerable<Contact>> GetAllContactsAsync()
    {
        if (FailGet)
        {
            throw new InvalidOperationException();
        }
        await Task.Delay(1000);
        return contacts;
    }
}

The property FailGet in the above class is used to force the mock to throw an exception. This is done just to cover more test cases.

In the test class, we need a TestInitialize method to arrange the objects needed for unit testing.

[TestClass]
public class ContactsControllerTests
{
    MockRepository repository;
    ContactsController contactsApi;

    [TestInitialize]
    public void InitializeForTests()
    {
        repository = new MockRepository();
        contactsApi = new ContactsController(repository);
    }
}

Let us test the GetContactsListAsync method first. Testing this method seems to be straight forward, as it returns either a plain generic list or throws an exception. But the test method can’t just return void like other tests, as the method is asynchronous. To test an asynchronous method, the test method should also be made asynchronous and return a Task. Following test checks if the controller action returns a collection of length 4:
[TestMethod]
public async Task GetContacts_Should_Return_List_Of_Contacts() 
{
    var contacts = await contactsApi.GetContactsListAsync();
    Assert.AreEqual(contacts.Count(), 4);
}

If the repository encounters an exception, the exception is re-thrown from the GetContactsListAsync method as well. This case can be checked using the ExpectedException attribute.
[TestMethod]
[ExpectedException(typeof(InvalidOperationException))]
public async Task GetContacts_Should_Throw_Exception()
{
    repository.FailGet = true;
    var contacts = await contactsApi.GetContactsListAsync();
}

Now let’s test the GetContactsHttpActionResultAsync method. Though this method does the same thing as the previous method, it doesn’t return the plain .NET objects. To test this method, we need to extract the result from the IHttpActionResult object obtained from the action method. Following test checks if the action result contains a collection when the repository is able to fetch results. Return type of Ok() method used above is OkNegotiatedContentResult. IHttpActionresult has to be converted to this type to check for the result obtained:
[TestMethod]
public async Task GetContactsHttpActionResult_Should_Return_HttpResult_With_Contacts()
{
    var contactsResult = await contactsApi.GetContactsHttpActionResultAsync() as OkNegotiatedContentResult<IEnumerable<Contact>>;

    Assert.AreEqual(contactsResult.Content.Count(), 4);
}

Similarly, in case of error, we are calling InternalServerError() method to return the exception for us. We need to convert the result to ExceptionResult type to be able to check the type of exception thrown. It is shown below:
[TestMethod]
public async Task GetContactsHttpActionResult_Should_Return_HttpResult_With_Exception()
{
    repository.FailGet = true;
    var contactsResult = await contactsApi.GetContactsHttpActionResultAsync() as ExceptionResult;
    Assert.IsInstanceOfType(contactsResult.Exception,typeof(InvalidOperationException));
}

Happy coding!

Monday, 22 July 2013

Isolate your tests from dependencies with TypeMock’s Isolator

Software development process is continuously evolving. One of the most talked practices in current era is Test Driven Development (TDD). There can’t be a day when I get into twitter and not seen some tweets on TDD and Unit testing. After some days, we may see very less number of projects that don’t have unit tests written.

If a piece of code is driven by tests, the code will not only have less bugs but the developers also spend some time to refactor and make the code cleaner. This makes the job of future developers easier, as they don’t have to take pain to write unit tests for a small piece that they write to add a new feature to the existing giant code base.

But we have a huge number of legacy projects for which we don’t have unit tests written. As most of such projects were not written with layers and abstractions, one will be more than scared to write automated unit tests for them. But these projects shouldn’t be left behind. A mocking framework with capability to mock out tight dependencies will make the work easier.

TypeMock’s Isolator is a right choice to pick in such scenarios. There are three versions of Isolator; the details on these versions are available on the product page.

To start using Isolator in a unit test project, a couple of assembly references have to be added. These dlls are added to GAC once you install Isolator. In C# projects, we need the references that are highlighted in the following screenshot.



In VB.NET projects, a reference to Typemock.Isolator.VisualBasic has of be added. These namespaces have to be included in the unit test class and the test methods have to be decorated with Isolate attribute as shown:


[TestMethod, Isolated]
public void Should_Set_value_To_Orders()
{

}


This attribute is used to keep each test method independent of each other.

Isolator has a uniform interface for mocking. Meaning, the API syntax to mock abstract types and concrete types is the same. Let us see how Isolator makes the process of writing unit tests easier in action.

Mocking interfaces
Let’s consider the following interface:


public interface IOrdersView
{
        IEnumerable<Order> Orders { get; set; }
        string this[string key] {get;}
        event EventHandler<EventArgs> LoadOrders;
}


It is a very generic interface which will be implemented by a view and can be used in any type of application. Let’s assume that it is used in an ASP.NET application following Model-View-Presenter pattern. The presenter will hold a reference of this interface type. While writing tests for the presenter, we need a mock object of this interface. Following statement creates the mock for us:

IOrdersView ordersView = Isolate.Fake.Instance<IOrdersView>();


Let’s fake behaviour of each of the component now. Let’s start with the property Orders.

Isolate.WhenCalled(()=>ordersView.Orders).WillReturn(new List<Order>(){
    //Use collection initializer to set values
       });


As we see, it is quite easy to skip mock implementation and return some custom values. The same API can be used to mock a method as well. Following statement fakes the event load orders.

Isolate.Invoke.Event(() => ordersView.LoadOrders += (s, e) => { 
     //A custom mock implementation goes here
      });


It is not necessary to implement a handler; it can be skipped by assigning null to the event handler. If the event accepts parameters, they can be passed after the mock implementation.

Faking an indexer is also similar to faking methods. While faking a method accepting parameters or indexers, we must specify value of the argument. Following statement is used to return a custom value when the indexer is asked to provide value of ID:


Isolate.WhenCalled(() => orders["ID"]).WillReturn("1");


Mocking Concrete types
Most of the legacy applications don’t follow rules of separation of concerns that we talk these days. For instance, if we take an old ASP.NET web forms based application, the code behind of each of the form is very heavily loaded with code. Testing such classes is not easy. Most scary object to deal with in ASP.NET code behind is HttpContext. This single object has a bunch of properties that are set by the web server when the application starts. Isolator’s API has a method that fakes all the properties in one go.


Isolate.WhenCalled(() => HttpContext.Current).ReturnRecursiveFake();


If there is a need to return some specific values when certain properties are invoked, you can do that using same API that we used for mocking interfaces. It is shown below:

var httpContextFake = Isolate.Fake.Instance<HttpContext>();
Isolate.WhenCalled(() => httpContextFake.Session["UserId"]).WillReturn("U001");
Isolate.WhenCalled(() => HttpContext.Current).WillReturn(httpContextFake);


Many applications contain a data access layer that is responsible to hit the database to operate on data from the application. Before technologies like Entity Framework came in, most of the projects used to perform database operations using ADO.NET. While writing tests for logic involving objects of SqlConnection and SqlCommand, we must prevent the tests from hitting the database. Isolator makes it possible to replace the actual objects with mocked objects on the fly. Following snippet demonstrates it:

var sqlCommandInstance = Isolate.Fake.Instance<SqlCommand>();
Isolate.Swap.NextInstance<SqlCommand>().With(sqlCommandInstance);


The first statement that creates the fake instance of SqlCommand mocks all methods defined in the class as well. After these statements, if we instantiate the data access layer and call a method that uses ExecuteNonQuery, then the call won’t hit the physical database. It will invoke the fake method that is just created.

These are some of the most common scenarios that we face during unit testing. Isolator is capable of doing much more than what is discussed here. Some of the eye-catching features include mocking:

  1. LINQ queries
  2. Private members
  3. Static members
  4. Counting calls
  5. Extension methods

To learn more on Typemock’s Isolator, you may visit the product page and checkout the online documentation.

Happy coding!

Sunday, 23 June 2013

Unit Testing AngularJS Controller Using QUnit and Sinon


Angular JS is known for and is becoming increasingly popular due to its nature of testability. Angular’s in-the- box abstractions make any amount of code easily testable. Code written using Angular JS can be tested using any JavaScript unit testing framework out there, may it be QUnit, Jasmine, Mocha or some other library.

In an older post, we wrote unit tests for the AngularShoppingCart application using Jasmine. In this post, we will discuss on unit testing Angular JS’ controller using QUnit and Sinon.

If you haven’t followed earlier posts, take a look at the code on GitHub.

QUnit, Sinon and setting up

QUnit is a JavaScript unit testing framework developed by jQuery team. It is used in the projects like jQuery, jQuery UI, jQUery Mobile. QUnit is a very simple and generic framework that can be used to test any piece of JavaScript code. Unlike Jasmine, QUnit doesn’t have built-in support for creating spies.

Sinon is a JavaScript library that makes the process of creating spies, mocks and stubs easier. It doesn’t depend on any other JavaScript library and easily integrates with any JavaScript unit test framework. Official site has a nice API documentation covering different features of the library.

QUnit tests run on an HTML page. We need to add references to following files in the page:

  1. QUnit library
  2. QUnit style sheet
  3. Sinon library
  4. Source files of the scripts to be tested
  5. File containing unit tests for above source
  6. Any other library (like jQuery, jQuery UI, Angular) on which the source depends

As we will be testing code written using Angular JS, we should include angular-mocks.js library, which has mock services to replace some of the most commonly used services.

Following is the HTML page to run QUnit tests:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>QUnit Test Runner</title>
    
    <!-- QUnit stylesheet -->
    <link href="../../Styles/qunit-1.11.0.css" rel="stylesheet" type="text/css" />
    
    <!-- QUnit for testing and Sinon for test spies, mocks and stubs -->
    <script src="../../Scripts/qunit-1.11.0.js" type="text/javascript"></script>
    <script src="../../Scripts/sinon-1.7.3.js" type="text/javascript"></script>
    
    <!-- JavaScript libraries on which source depends -->
    <script src="../../Scripts/angular.js" type="text/javascript"></script>
    <script src="../../Scripts/angular-mocks.js" type="text/javascript"></script>
    
    <!-- Script source to test and other files on which source depends -->
    <script src="../../Scripts/app/ShoppingModule.03.js" type="text/javascript"></script>
    <script src="../../Scripts/app/ShoppingCartController.03.js" type="text/javascript"></script>
    <script src="../../Scripts/app/CartCheckoutController.js" type="text/javascript"></script>
    
    <!-- Test Script -->
    <script type="text/javascript" src="ShoppingCartControllerSpec.js"></script>
    <!--<script src="CartCheckoutTestSpec.js" type="text/javascript"></script>-->
</head>
<body>
    <div id="qunit">
    </div>
    <div id="qunit-fixture">
    </div>
</body>
</html>

Specs and Suits

QUnit has a set of blocks to create modules, setup required resources, clear them after running the tests, create a test suit and a number of assertions. Following are the blocks that we will be using:

  1. module: Defines a module, which can be used to group a number of related tests. Two functions namely, setup and teardown can be added to the module to instantiate and clear the resources for unit tests
  2. test: Used to define a test spec. Accepts a name and function containing logic to be executed. The logic contains assertions to evaluate the behaviour
  3. ok: A boolean assertion, that passes when the argument returns a Boolean true
  4. equal: An assertion that compares two values and passes if they are equal. We also have notEqual assertion that passes if the values are not equal

QUnit’s API documentation page contains details of all available blocks and asserts.

Sinon Spies and Stubs

Sinon is a very rich library with a huge API and a lot of features. We need very few of them in our specs:

  1. spy: A spy can be an anonymous function or a wrap around an existing function. There are a number of ways to create and check if the spy is invoked. We will be using one of the approaches.
    sinon.spy(obj,”methodName”) – creates a spy for a method with specified name
    obj.methodName.called – to check if the method is called
    obj.methodName.restore() – to restore the original functionality of the method
  2. stub: Stubs are spied with existing behaviour. They should be used when we want a function to behave in a way we want. We will be using the following syntax to create a stub in the unit test that we are going to write in a while:
    sinon.stub(obj,”methodName”, functionName) – Replaces the function with passed name with the logic of an existing function
Unit testing ShoppingCartController

Let’s start testing the functions defined in ShoppingCartController.

Dependencies of the controller are clearly visible from the signature. As we need to inspect behaviour of the controller in isolation, we must mock these services. Following is the signature of ShoppingCartController:

function ShoppingCartCtrl($scope, $window, shoppingData, shared) {
}

As these services will be used across specs, it is better to create them globally and initialize them in setup block. Since we will not hit the actual service, we need to use some static data to make the job of testing AJAX calls easier.
var shoppingCartStaticData = [
    { "ID": 1, "Name": "Item1", "Price": 100, "Quantity": 5 },
    { "ID": 2, "Name": "Item2", "Price": 55, "Quantity": 10 },
    { "ID": 3, "Name": "Item3", "Price": 60, "Quantity": 20 },
    {"ID": 4, "Name": "Item4", "Price": 65, "Quantity": 8 }
];
 
//Mocks
var windowMock, httpBackend, _shoppingData, sharedMock;
 
//Injector
var injector;
 
//Controller
var ctrl;
 
//Scope
var ctrlScope;
 
//Data
var storedItems;


We need to create a module to initialize all of the above objects and clear them. Following is the skeleton of the module:
module(“Shopping module”, {
 setup: function(){
  //Initialize all above objects
 },
 teardown: function(){
  //Clear up objects and restore spies
 }
});

Resolving Dependencies

Unlike Jasmine, in QUnit tests we need to use injector to get the dependencies resolved. They aren’t resolved automatically. Following statement gets an instance of the injector:

injector = angular.injector(['ng', 'shopping', 'appMocks']);
First and most important dependency of the controller is the $scope service. We need to create our own scope and pass it as a parameter while creating object of the controller. Using $rootScope, it is very easy to create our own scope.
ctrlScope = injector.get('$rootScope').$new();

Second dependency is the $window service. As we are using href property of location alone, we can create a custom object with this property alone.
windowMock = { location: { href: ""} };

Third dependency shoppingData service is a wrapper to call backend data services. It used another service, $http to send AJAX requests. Angular JS team has made our job easy by creating $httpBackend, a mock for $http. $httpBackend provides a nice interface to send our own response when an AJAX request is made. In QUnit tests, a decorator statement must be added to get the object of $httpBackend. Following snippet shows it:
var appMocks = angular.module("appMocks", []);
 
appMocks.config(function ($provide) {
    $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);
});
shoppingData service has three functions: getAllItems, addAnItem and removeItem. We need to create stubs for these functions with a call to the original function. The stubs will be used to inspect if the function is called. Following snippet demonstrates it:
httpBackend = injector.get('$httpBackend');
_shoppingData = injector.get('shoppingData');
sinon.stub(_shoppingData, "getAllItems", _shoppingData.getAllItems);
sinon.stub(_shoppingData, "addAnItem", _shoppingData.addAnItem);
sinon.stub(_shoppingData, "removeItem", _shoppingData.removeItem);

The function getAllItems sends an HTTP GET request to the service. Following statement configures a custom response on $httpBackend when Angular detects any such request:
httpBackend.expectGET('/api/shoppingCart/').respond(storedItems);

Fourth and final dependency is the shared service. Following snippet creates a mock shared service with a spy for setCartItems, the only function used in ShoppingCartCtrl:
sharedMock = injector.get('shared');
sinon.spy(sharedMock, 'setCartItems');

Now that we have all the mocks ready, let’s create an object of the controller.
ctrl = injector.get('$controller')(ShoppingCartCtrl, { $scope: ctrlScope, $window: windowMock, shoppingData: _shoppingData, shared: sharedMock });

All spies have to be restored in the teardown block as shown below:
teardown: function () {
    sharedMock.setCartItems.restore();

    _shoppingData.getAllItems.restore();
    _shoppingData.addAnItem.restore();
    _shoppingData.removeItem.restore();
 }

Testing behaviour of the controller

Note: If you have already read the post on Jasmine, you may skip rest of the post and check the code as most of the explanation remains same

On creation of the controller, it calls getAllItems function of shoppingData service to fetch details of all items. The test for this behaviour should check if the right function is called and if it sets value to the items property. Following test shows this:

 test("Should call getAllItems function on creation of controller", function () {
     ok(_shoppingData.getAllItems.called, "getAllItems is called");
     httpBackend.flush();
     notEqual(storedItems.length, 0, "Number of items loaded is not 0");
 });

Upon calling addItem function of the controller, it calls addAnItem function of shoppingData service. As it makes an HTTP post request to the service, $httpBackend should be configured to respond when it finds a post request. Test looks as follows:
 test("Should call addAnItem function of the shoppingData service", function () {
  httpBackend.expectPOST('/api/shoppingCart/', {}).respond(storedItems.push({ "Id": 5, "Name": "Item5", "Price": 70, "Quantity": 10 }));
     ctrlScope.addItem({});
     ok(_shoppingData.addAnItem.called, "addAnItem function is called");
     httpBackend.flush();
     equal(storedItems.length, 5, "New item is added to the list");
});

The function removeItem can also be tested in similar way. But, what if a request fails? The $errorMessage property of scope should be assigned with a friendly error message. A request can be forced to fail by passing a JavaScript object literal with an error status code to $httpBackend. Let’s see this in action:
 test("Should assign an error message", function () {
     httpBackend.expectDELETE('/api/shoppingCart/1').respond({ status: 500 });
      ctrlScope.removeItem(1);
 notEqual(ctrlScope.errorMessage,"","An error message is set to the variable in scope");
 });

mySortFunction is used to convert numeric value to number. We can test this function by passing a number in the form of a string and checking if it returned a number to us. We need to set the property sortExpression before calling the function.
 test("Should return a number when a number is passed in", function () {
     var item = { "Number": "123" };
     ctrlScope.sortExpression = "Number"; 
     var numVal = ctrlScope.mySortFunction(item);
     equal(typeof numVal, "number", "Value returned is a number");
 });

The totalPrice function is very easy to test, as we need to just check if it sets some value to the returned variable.
 test("Should calculate totalPrice", function () {
     ctrlScope.items = storedItems;
     notEqual(ctrlScope.totalPrice(), 0, "Total price is calculated");
 });

On click of Purchase Items link on the page, the user has to be navigated to CheckoutItems view and setCartItems function of shared service should be called to pass the items array to the second view. As we are setting navigation URL to window.location.href, for which we created a mock, the test has to check if this property is set to some value. Following test verifies these functionalities:
 test("Should set value in shared and value of href set", function () {
     ctrlScope.items = storedItems;
     ctrlScope.purchase();
     ok(sharedMock.setCartItems.called, "setCartItems function is called");
     notEqual(windowMock.location.href,"","URL of the page is modified");
 });

Now view the test runner page on browser. All the tests should be passed. I encourage you to play a bit with the code and tests and check the result of test after the changes. This way, we will get to know more about using QUnit, Sinon with Angular JS and also about unit testing.

You can download the code including unit tests from the following GitHub repo: AngularShoppingCart

Happy coding!

Saturday, 6 April 2013

Unit Testing AngularJS Controller Using Jasmine

Building and using single page JavaScript applications is fun. It brings richness on client side without having to install any external plugins. While building these applications, we write a lot of JavaScript code to run on client side. Releasing such large amount of code to client without testing will be a sin. We might leave the code with some unnoticed bugs if we do not test.

Right from the first post on Angular JS, I have mentioned several times that unit testability is one of its primary design goals. Tutorial series on Angular’s website demonstrates end-to-end testing using Jasmine’s BDD style. I cannot have sound sleep unless I write some tests for the AngularShoppingCart application. In this post, we will see how a controller can be unit tested using Jasmine.

Note: If you are looking for a tutorial on unit testing using QUnit, I have a blog post on it: Unit Testing Angular JS Controller Using QUnit and Sinon

If you haven’t followed earlier posts, take a look at the code on GitHub.

Jasmine and setting up
Jasmine is a BDD (Behaviour Driven Development) framework for testing JavsScript code. It doesn’t depend on any other JavaScript library. It has nice support to create spies (mocks), which helps to easily get rid of some concrete dependencies. Jasmine can be used to unit test anything written in JavaScript.

In order to run jasmine tests and view their results, we need to create an HTML page. Following references should be added to the page:

  1. Jasmine core library
  2. Jasmine HTML library
  3. Jasmine style sheet
  4. Source files of the script to be tested, which is also referred as System under test (SUT)
  5. File containing unit tests for the above source
  6. Any other library (like jQuery, jQuery UI, Angular) on which the source depends

As we will be testing code written using Angular JS, we should include angular-mocks.js library, which has mock services to replace some of the most commonly used services.

In body tag of the HTML page, a couple of statements are to be added to bootstrap Jasmine. Following is the template of a Jasmine spec runner page:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <title>Jasmine Test Runner</title>

    <!-- Jasmine stylesheet -->
    <link rel="stylesheet" type="text/css" href="../../Styles/Jasmine.css">
 
    <!-- Jasmine core and HTML -->
    <script type="text/javascript" src="../../Scripts/jasmine.js"></script>
    <script type="text/javascript" src="../../Scripts/jasmine-html.js"></script>
    <script type="text/javascript" src="../../Scripts/jasmine.async.js"></script>
 
    <!-- JavaScript libraries on which source depends -->
    <script type="text/javascript" src="../../Scripts/angular.js"></script>
    <script type="text/javascript" src="../../Scripts/angular-mocks.js"></script>
 
    <!-- Script source to test and other files on which source depends -->
    <script type="text/javascript" src="../../Scripts/app/ShoppingModule.03.js"></script>
    <script type="text/javascript" src="../../Scripts/app/ShoppingCartController.03.js"></script>
    <script type="text/javascript" src="../../Scripts/app/CartCheckoutController.js"></script>
    
    <!-- Test script -->
    <script type="text/javascript" src="ShoppingCartControllerSpec.js"></script>
    <!--<script type="text/javascript" src="CartCheckoutTestSpec.js"></script>-->
</head>
<body>
    <script type="text/javascript">
        jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
        jasmine.getEnv().execute();
    </script>
</body>
</html>

Specs and Suits
Jasmine has a set of functions defined to create suits, specs and assertions. Following listing explains each of them in brief:

  1. describe: Used to define a suite. Accepts two parameters, name of the suite and a function containing statements to be contained in a suite
  2. it: Used to define a spec. Accepts a name and function containing logic to be executed. The logic contains assertions to evaluate the behaviour
  3. beforeEach: To set up dependencies before any spec under a suite runs
  4. afterEach: To clear any dependency after being used in the test cases
  5. expect: A function that accepts an object to be asserted
  6. matcher: Jasmine defines several matchers like toBe, toHaveBeenCalled, toEqual to perform a Boolean match between actual and expected values. We can write custom matchers too

In-depth discussion about above topics is beyond the scope of this article. Refer to Jasmine’s documentation for more details.

Unit testing ShoppingCartController
Let’s start testing the functions defined in ShoppingCartController.

Dependencies of the controller are clearly visible from the signature. As we need to inspect behaviour of the controller in isolation, we must mock these services. Following is the signature of ShoppingCartController:

function ShoppingCartCtrl($scope, $window, shoppingData, shared) {
}

As these services will be used across specs, it is better to create them globally and initialize them in beforeEach block. Since we will not hit the actual service, we need to use some static data to make the job of testing AJAX calls easier.
var shoppingCartStaticData = [
    { "ID": 1, "Name": "Item1", "Price": 100, "Quantity": 5 },
    { "ID": 2, "Name": "Item2", "Price": 55, "Quantity": 10 },
    { "ID": 3, "Name": "Item3", "Price": 60, "Quantity": 20 },
    {"ID": 4, "Name": "Item4", "Price": 65, "Quantity": 8 }
];
 
describe("ShoppingCartCtrl", function () {
 
    //Mocks
    var windowMock, httpBackend, _shoppingData, sharedMock;
 
    //Controller
    var ctrl;
 
    //Scope
    var ctrlScope;
 
    //Data
    var storedItems;
 
    //Loading shopping module
    beforeEach(function () {
        module("shopping");
    });
 
    beforeEach(inject(function ($rootScope, $httpBackend, $controller, shoppingData) {
        //Mock the services here
    }

});

The second beforeEach block will set-up all dependencies for the controller. So, it needs a number of services to perform its job. We will discuss their importance in shortly.

Resolving Dependencies
First and most important dependency of the controller is the $scope service. We need to create our own scope and pass it as a parameter while creating object of the controller. Using $rootScope, it is very easy to create our own scope:

ctrlScope = $rootScope.$new();

Second dependency is the $window service. As we are using href property of location alone, we can create a custom object with this property alone.
windowMock = { location: { href: ""} };

Third dependency shoppingData service is a wrapper to call backend data services. It used another service, $http to send AJAX requests. Angular JS team has made our job easy by creating $httpBackend, a mock for $http. $httpBackend provides a nice interface to send our own response when an AJAX request is made.

shoppingData service has three functions: getAllItems, addAnItem and removeItem. Let’s create spies for these functions as follows:

httpBackend = $httpBackend;
_shoppingData = shoppingData;
spyOn(shoppingData, 'getAllItems').andCallThrough();
spyOn(shoppingData, 'addAnItem').andCallThrough();
spyOn(shoppingData, 'removeItem').andCallThrough();

The function andCallThrough delegate calls to the actual implementations. The function getAllItems sends an HTTP GET request to the service. Following statement configures a custom response on $httpBackend when Angular detects any such request:
httpBackend.expectGET('/api/shoppingCart/').respond(storedItems);

Fourth and final dependency is the shared service. Following snippet creates a mock shared service with a spy for setCartItems, the only function used in ShoppingCartCtrl:
sharedMock = {
    setCartItems: jasmine.createSpy('setCartItems')
};

Now that we have all the mocks ready, let’s create an object of the controller.
ctrl = $controller(ShoppingCartCtrl, { $scope: ctrlScope, $window: windowMock, shoppingData: _shoppingData, shared: sharedMock });

Testing behaviour of the controller
On creation of the controller, it calls getAllItems function of shoppingData service to fetch details of all items. The test for this behaviour should check if the right function is called and if it sets value to the items property. Following test shows this:

it("Should call getAllItems function on creation of controller and set items property", function () {
    expect(_shoppingData.getAllItems).toHaveBeenCalled();
    httpBackend.flush();
    expect(ctrlScope.items.length).not.toBe(0);
});

Upon calling addItem function of the controller, it calls addAnItem function of shoppingData service. As it makes an HTTP post request to the service, $httpBackend should be configured to respond when it finds a post request. Test looks as follows:
it("Should call addAnItem function of the shoppingData service", function () {
    httpBackend.expectPOST('/api/shoppingCart/', {}).respond(storedItems.push({ "Id": 5, "Name": "Item5", "Price": 70, "Quantity": 10 }));
    ctrlScope.addItem({});
    expect(_shoppingData.addAnItem).toHaveBeenCalled();
    httpBackend.flush();
    expect(storedItems.length).toBe(5);
});

The function removeItem can also be tested in similar way. But, what if a request fails? The $errorMessage property of scope should be assigned with a friendly error message. A request can be forced to fail by passing a JavaScript object literal with an error status code to $httpBackend. Let’s see this in action:
it("Should assign an error message", function () {
    httpBackend.expectDELETE('/api/shoppingCart/1').respond({ status: 500 });
    ctrlScope.removeItem(1);
    expect(ctrlScope.errorMessage).not.toBe("");
});

mySortFunction is used to convert numeric value to number. We can test this function by passing a number in the form of a string and checking if it returned a number to us. We need to set the property sortExpression before calling the function.
it("Should return a number when a number is passed in", function () {
    var item = { "Number": "123" };
    ctrlScope.sortExpression = "Number";
    var numVal = ctrlScope.mySortFunction(item);
    expect(typeof numVal).toBe("number");
});

The totalPrice function is very easy to test, as we need to just check if it sets some value to the returned variable.

On click of Purchase Items link on the page, the user has to be navigated to CheckoutItems view and setCartItems function of shared service should be called to pass the items array to the second view. As we are setting navigation URL to window.location.href, for which we created a mock, the test has to check if this property is set to some value. Following test verifies these functionalities:

it("Should set value in shared and value of href set", function () {
    ctrlScope.items = storedItems;
    ctrlScope.purchase();
 
    expect(sharedMock.setCartItems).toHaveBeenCalled();
    expect(windowMock.location.href).not.toBe("");
});

Now view the test runner page on browser. All the tests should be passed. I encourage you to play a bit with the code and tests and check the result of test after the changes. This way, we will get to know more about Jasmine's behavior as well as unit testing.

You can download the code including unit tests from the following GitHub repo: AngularShoppingCart

Happy coding!

Saturday, 17 November 2012

Unit Testing Asynchronous methods using MSTest and XUnit

As we saw in previous posts, writing asynchronous code has become quite easy with .NET framework 4.5. To be able to write well and bug less code in any framework or language, unit tests play a vital role. Unit testing asynchronous code is a bit tricky and it is currently not supported by all unit test frameworks. In this post, we will see how to unit test an asynchronous method using MSTest and the XUnit framework.

Irrespective of the unit testing framework used, the test method written to test the asynchronous method has to follow a set of rules.
  • Test method should be marked as async
  • await keyword should be used while calling the method to be tested
  • Return type of the test method should be Task

I will be using the following asynchronous method for unit testing. It is a very simple method (I have used it in my post on Asynchronizing a C# method using async and await), that divides two numbers with a delay of 2 seconds.
public class ArithemticOperations
{
    public async Task<double> DivideAsync(int first, int second)
    {
        await Task.Delay(2000);
        return (double)second / first;
    }
} 

Unit testing using MSTest

MSTest is the testing framework built into Visual studio. If you are familiar with it, then testing asynchronous method doesn’t require much learning. If you are not already familiar with MSTest, you may go through Unit Testing Framework portion on MSDN.

Testing an asynchronous method is much similar to testing a synchronous method. We just need to follow the rules mentioned above. Following is a test class that tests the divide method created above.
[TestClass]
public class AsyncMethodUnitTests
{
    [TestMethod]
    public async Task DivideAsync_Returns_RightResult()
    {
        int first = 10, second = 20;
        double expected = 2.0;
        ArithemticOperations operations = new ArithemticOperations();
        double actual = await operations.DivideAsync(first, second);
        Assert.AreEqual(actual, expected);
    }
}


Unit testing using XUnit

XUnit is created by James Newkirk and Brad Wilson. It is built to support Test Driven Development with a design goal of simplicity. You may visit the Codeplex site of XUnit to learn more about it.

Testing asynchronous code using XUnit is very straight forward. Following is a test class that tests the divide method:
public class AsyncTests
{
    [Fact]
    public async Task AsyncDivide_Returns_RightResult()
    {
        int first = 10, second = 20;
        double expected = 2;
        ArithemticOperations operations = new ArithemticOperations();
        double actual = await operations.DivideAsync(first, second);
        Assert.Equal(actual, expected);
    }
}

Along with making your code run better by applying asynchronous strategies, you can unit test and even test drive them.

Happy coding!