Brk
Brk

Reputation: 1297

how to test an AngularJS service with rest calls in Jasmin

Hey I am new to AngularJS testing, I am trying to figure out,

  1. How should I test an AngularJS service which is responsible for my rest calls.

  2. How do I called this service in other controllers which I want to test.

I need to test the datafactory service which use rest requests The code which need to be tested is like this:

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

app.controller("mainCTRL", ["$scope","dataFactory",function($scope,dataFactory){
  $scope.title = "Hello World";
  dataFactory.getEntries("fakeSuffix");
  
  }]);

app.factory('dataFactory', ['$http', '$window', '$log', function ($http, $window, $log) {
            var urlBase = $window.location.origin + '/api',
                dataFactory = {};
            /**
            * get all Entries.
            **/
            dataFactory.getEntries = function (suffix) {
                $log.debug("************ Get All Entries ************");
                $log.debug("url:", urlBase + suffix);
                return $http.get(urlBase + suffix, { headers: { cache: false } });
            };

            /**
            * get single Entry.
            **/
            dataFactory.getEntry = function (id) {
                $log.debug("************ Get Single Entry ************");
                return $http.get(urlBase + '/' + id);
            };

            /**
            * insert Entry
            **/
            dataFactory.postEntry = function (method, entry) {
                var url = urlBase + '/' + method;
                return $http.post(url, entry);

            };

            /**
            * update Entry
            **/
            dataFactory.updateEntry = function (entry) {
                $log.debug("************ Update Single Entry ************");
                return $http.put(urlBase + '/' + entry.id, entry);
            };

            /**
            * delete Entry
            **/
            dataFactory.deleteEntry = function (id) {
                $log.debug("************ Delete Single Entry ************");
                return $http.delete(urlBase + '/' + id);
            };

            return dataFactory;
        }]);
<script src="https://ajax.googleapis.com/ajax/libs/jQuery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div id="block" ng-app="app" ng-controller="mainCTRL">
{{title}}
</div>

Upvotes: 0

Views: 1142

Answers (3)

SiddAjmera
SiddAjmera

Reputation: 39432

Q.1 - How should I test an AngularJS service which is responsible for my rest calls.
Ans. - I've written a test case for one of your services' methods below. You can write similar test cases for other methods.

Q.2 - How do I called this service in other controllers which I want to test.
Ans. - In the code below, as you are writing test cases for your service which is relying on $http's get, post, put and delete methods, I've injected $httpBackend in the test cases and mocked all these methods in beforeEach block. Similarly, when you'll be writing test cases for your controller which would be depending on this service, you'll have to use a similar approach. Just inject the service in your controller's test case and mock all the methods of your service that would be called from your controller.

//AngularJS Code

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

app.controller("mainCTRL", ["$scope","dataFactory",function($scope,dataFactory){
    $scope.title = "Hello World";
    dataFactory.getEntries("fakeSuffix");  
}]);

app.factory('dataFactory', ['$http', '$window', '$log', function ($http, $window, $log) {
    //var urlBase = $window.location.origin + '/api', 
    var urlBase = '/api',   //Change here.
    dataFactory = {};
    /**
    * get all Entries.
    **/
    dataFactory.getEntries = function (suffix) {
        $log.debug("************ Get All Entries ************");
        $log.debug("url:", urlBase + suffix);
        return $http.get(urlBase + suffix, { headers: { cache: false } });
    };

    /**
    * get single Entry.
    **/
    dataFactory.getEntry = function (id) {
        $log.debug("************ Get Single Entry ************");
        return $http.get(urlBase + '/' + id);
    };

    /**
    * insert Entry
    **/
    dataFactory.postEntry = function (method, entry) {
        var url = urlBase + '/' + method;
        return $http.post(url, entry);
    };

    /**
    * update Entry
    **/
    dataFactory.updateEntry = function (entry) {
        $log.debug("************ Update Single Entry ************");
        return $http.put(urlBase + '/' + entry.id, entry);
    };

    /**
    * delete Entry
    **/
    dataFactory.deleteEntry = function (id) {
        $log.debug("************ Delete Single Entry ************");
        return $http.delete(urlBase + '/' + id);
    };

    return dataFactory;
}]);

//Jasmine Test Case
describe('factory: dataFactory', function() {

    var dataFactory, $http, $window, $log, $httpBackend;

    beforeEach(module('app'));

    beforeEach(inject(function (_dataFactory_, _$http_, _$window_, _$log_, _$httpBackend_) {
        dataFactory = _dataFactory_;
        $http = _$http_;
        $window = _$window_;
        $log = _$log_;
        $httpBackend = _$httpBackend_;

        $httpBackend.when('GET', "/api/suffix").respond({
            status: 200,
            data: "data"
        });

        $httpBackend.when('GET', "/api/id").respond({
            status: 200,
            data: "data"
        });

        $httpBackend.when('POST', "/api/method").respond({
            status: 200,
            data: "data"
        });

        $httpBackend.when('PUT', "/api/id").respond({
            status: 200,
            data: "data"
        });

        $httpBackend.when('DELETE', "/api/id").respond({
            status: 200,
            data: "data"
        });
    }));

    afterEach(function() {
        $httpBackend.verifyNoOutstandingExpectation();
        $httpBackend.verifyNoOutstandingRequest();
    });

    describe('function: getEntries', function(){
        //A sample test case for getEntries
        it('should get all enteries', function(){
            var response = dataFactory.getEntries("/suffix");
            response.then(function(res){
                expect(res.status).toEqual(200);
            });
            $httpBackend.flush();
        });
    });

    //Similarly write tests for the rest of functions.

});

Hope this helps.

Upvotes: 1

jcubic
jcubic

Reputation: 66560

Try this, found in answer to this question Injecting a mock into an AngularJS service

  module(function($provide) {
      $provide.value('$http', {
          get: function(url, options) {
              // your get implementation
          },
          post: function(url, data) {
              // your post implementation
          },
          'delete': function(url) {
              // your delete implementation
          },
          put: function(url, data) {
              // your put implementation
          }
      });
  });

Upvotes: 1

PrabaharanKathiresan
PrabaharanKathiresan

Reputation: 1129

As for as I know, To test service, create the Jasmine test case similar to controller with out controller initialisation.

To Test the controllers based on service response create spyOn for the respective service and mock the service response.

Upvotes: 1

Related Questions