Skip to content

Promise(service) Test Cases

Akshay Prasad edited this page Dec 26, 2016 · 9 revisions

Promise Concept:

Before going to Promise Test Case,let us go through some of the required concepts in order to test the Promise.

$q concept:

  • A service that helps you run functions asynchronously, and use their return values (or exceptions) when they are done
    processing.
  • $q constructor which takes a resolver function as the first argument.
function asyncGreet(name) {
  // perform some asynchronous operation, resolve or reject the promise when appropriate.
  return $q(function(resolve, reject) {
    setTimeout(function() {
      if (okToGreet(name)) {
        resolve('Hello, ' + name + '!');
      } else {
        reject('Greeting ' + name + ' is not allowed.');
      }
    }, 1000);
  });
}

var promise = asyncGreet('Robin Hood');
promise.then(function(greeting) {
  alert('Success: ' + greeting);
}, function(reason) {
  alert('Failed: ' + reason);
});

The Deferred API:

A new instance of deferred is constructed by calling $q.defer().

The purpose of the deferred object is to expose the associated Promise instance as well as APIs that can be used for signaling the successful or unsuccessful completion, as well as the status of the task.

Methods:

  • resolve(value) – resolves the derived promise with the value. If the value is a rejection constructed via $q.reject,
    the promise will be rejected instead.
  • reject(reason) – rejects the derived promise with the reason. This is equivalent to resolving it with a rejection constructed via $q.reject.
  • notify(value) - provides updates on the status of the promise's execution. This may be called multiple times before the promise is either resolved or rejected.

Angular Promise:

project you will find yourself dealing with a lot of callback functions and/or asynchronous calls to retrieve data from the back-end. To keep things smooth promises come to our rescue.

Promise Introduction:

1. Create deferred object:

The deferred object controls the state of the promise. We can trigger three resolutions: resolve, reject and notify. In the following steps we will see how it relates to the promise setup. This is how you create a deferred object:

var deferred = $q.defer();

2. Setup promise

In order to use the deferred object we need to setup the promise handlers before. This will be the code executed for each resolution. The scenarios are: success, failure and progress notification. The promise object is a property of the deferred object.

var promise = deferred.promise;

//basic version
promise.then(fnSuccess)
  .catch(fnFailure) //optional
  .finally(fnAlways) //optional

//advanced version
promise.then(fnSuccess, fnFailure, fnNotification)
  .catch(fnFailure) //optional
  .finally(fnAlways) //optional

3. Defer resolution

Once we have created the deferred object and setup the promise, we can execute our asynchronous processing and trigger the promise with the final resolution.

app.factory("Movies", function($http, $q) {
  return {
    get: function() {
        var deferred = $q.defer();
        $http.get('movies.json')
        .then(function(response){
           deferred.resolve(response.data);
        })
        .catch(function(error){
          deferred.reject(error);
        });
        return deferred.promise;
    }
  }
})

Testing a promise:

The promise of a service is tested by the knowledge of the above mentioned concepts:

var apps = angular.module('myApp',[]);
apps.factory('LanguagesServicePromise', ['$http', '$q', function($http, $q){
  var lng = {};
  lng.get = function() {
    var deferred = $q.defer();
    $http.get('languages.json')
    .then(function(response){
       var languages = response.data.map(function(item){
         console.log('aaaaaaaaa',item.name);
         return item.name;
       });
       deferred.resolve(languages);
    })
    .catch(function(response){
      deferred.reject(response);
    });
    return deferred.promise;
  };

  return lng;
}]);

describe('Testing Languages Service - Promise', function(){
  var LanguagesServicePromise,
    $httpBackend,
    jsonResponse = [{'name':'en'}, {'name':'es'}, {'name':'fr'}];

  beforeEach(function(){
    module('myApp');
    inject(function($injector){
      LanguagesServicePromise = $injector.get('LanguagesServicePromise');
      // set up the mock http service
      $httpBackend = $injector.get('$httpBackend');


    });
  });

  it('should return available languages', function() {

    // backend definition response common for all tests
    $httpBackend.expectGET('languages.json')
      .respond( jsonResponse );

    // service returns a promise
    var promise = LanguagesServicePromise.get();
    // use promise as usual
    promise.then(function(languages){
      // same tests as before
      console.log('languages');
      console.log(languages);
      expect(languages).toContain('en');
      expect(languages).toContain('es');
      expect(languages).toContain('fr');
      expect(languages.length).toEqual(3);
      // Spec waits till done is called or Timeout kicks in
      
    });
    // flushes pending requests
   $httpBackend.flush();
 });
});