Subscribe via RSS Feed

Angular.js Tests with Jasmine

August 1, 2013 8 Comments

We have previously written about javascript based testing framework - JavaScript Testing Framework – Jasmine – a quick study

In current post we are trying to discuss the Angular.js client side testing with Jasmine Testing Framework. We have covered the testing of Client side Controller and Angular Mock Service with Jasmine Framework. Codes are commented to help understanding of the testing.

Our 2 Example Controllers are -

// controllers.js
// This controller returns three json elements in $scope variable 
function PhoneListCtrl($scope) {
  $scope.phones = [
    {"name": "Nexus S",
     "snippet": "Fast just got faster with Nexus S."},
    {"name": "Motorola XOOM™ with Wi-Fi",
     "snippet": "The Next, Next Generation tablet."},
    {"name": "MOTOROLA XOOM™",
     "snippet": "The Next, Next Generation tablet."}
  ];
}

and

// RTcontroller.js
// In this controller we have created a service, from which data will be returned in "stocks" variable of angular  // $scope via $http and $q object.  

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

app.controller('StockListCtrl', function($scope, stockService) { // Angular Controller Definition 
                                                                 // with service injection
        stockService.getStocks().then(function(data) {           // Angular promise
            $scope.stocks = data;
        });
   });

app.factory('stockService', function($http, $q) {               // Angular Service Declaration
    return {
        getStocks: function() {                                 
            var deferred = $q.defer();                          // Deferred Object Declaration
            $http.get('stocks.json').success(function(data) {   // Asynchronous Service calling
                 deferred.resolve(data);
            }).error(function(){
                 deferred.reject();
            });
        return deferred.promise;
     }
   }
});

Following code is the specification file for testing which can be run with testrunner.html, which is default file for testing in Jasmine Framework. We have modified this file only for our example work.

The source files are to be included in

<!– include source files here…–> section of testrunner.html

<script type=”text/javascript” src=”src/controllers.js”></script>
<script type=”text/javascript” src=”src/RTcontroller.js”></script>

Also the spec file is to be included in

<!– include spec files here…–> section of testrunner.html

<script type=”text/javascript” src=”spec/ControllerSpec.js”></script>

Now the spec file -

 // The Angular.js test spec coding
describe('Controller function', function() {  // Jasmine Test Suite

  describe('PhoneListCtrl', function() {      // Inner Test suite for Angular Controller
    var scope;

    beforeEach(inject(function($rootScope, $controller) {  // Data initialisation in case of Headless Browser
                                                           // $rootScope is the Angular Built-in object from which
                                                           // angular scope will be created.
      scope = $rootScope.$new();
      var ctrl = $controller(PhoneListCtrl, {$scope: scope}); // Controller object will be created for the 
                                                              // PhoneListCtrl controller in testing environment.
    }));

    it('should create "phones" model with 3 phones', function() { 
      expect(scope.phones.length).toBe(3); // Individual Test Component - refer to source javaScript code
    });                                    // of the above Angular Controller
  });

  describe('StockListCtrl', function() {
     var scope;
     var $httpBackend, $rootScope, createController, _stockService;

	 beforeEach(function () {
            module("angularjstest");   // Angular Module Initialisation
        }); 

    beforeEach(inject(function($rootScope, $controller, $injector ,stockService) {

	  $httpBackend = $injector.get('$httpBackend'); // Mock object for Testing Environment with $http service 
	  $httpBackend.when('GET', 'stocks.json').respond([{"Product": "REL", "BBP": "10", 
                                                           "BSP": "10.2", "LTP": "10.1"}]); 
                             // Send the mock data by creating $httpbackend service
	  $rootScope = $injector.get('$rootScope');
	  scope = $rootScope.$new();
	  var $controller = $injector.get('$controller'); // Creating the Angular Controller for Test Environment
	  _stockService = stockService;
	  spyOn(stockService, 'getStocks').andCallThrough(); // Calling of the 'getStocks' method is ensured// by spyOn 
	  createController = function() { // Method to create controller 
              return $controller('StockListCtrl', {'$scope' : scope }, {stockService : _stockService});
          }; 

    }));

    it('should call getStocks', function() {
	  var controller = createController();
	  expect(_stockService.getStocks).toHaveBeenCalled(); // Service method is called or not
	  $httpBackend.flush();
    });
    it('should have more than 0 stock', function() {
	  var controller = createController();
	  $httpBackend.flush();
          expect(scope.stocks.length).not.toBe(0); // some stock data is expected to be returned from here -
                                                   // We have created mock service for this above.

    });
  });
});

So in the current post, we have covered testing of Angular Controller with and without Angular Services. We will cover any more complex scenario of testing with other examples as we come across our work.

If you find this post helpful, you can connect us in Google+ and Twitter

Enter your email address:

Delivered by FeedBurner