How to write jasmine test for following angular service which uses API and call backs

112 Views Asked by At

In my AngularJS application, I am having trouble figuring out how to unit test the following code:

This is the service being used by my test controller:

angular
    .module('web.template')
    .factory('testService', testService);

testService.$inject = ['$http'];

function testService($http) {
   return { 
        getTestDatas: function (callback) {
        var data = {
            'testParams': "test"
        };

        $http.post('http://localhost/test/post', data)
            .success(function (response) {
                callback(response);
            });
        },
    };
};
1

There are 1 best solutions below

0
On BEST ANSWER

As described in the docs you can use $httpBackend to make a mock for $http.

You can test both ways of implementing the service (callback or promise). But I also think that promises are better to test and should be preferred.

Just include ngMock in your dependencies and then you can create a fake response for your url.

Please have a look at the demo below (not working on SO, need to check what's the problem) or the working demo at jsFiddle

angular
    .module('web.template', ['ngMock'])
    .controller('mainCtrl', MainCtrl)
    .factory('testService', testService);

testService.$inject = ['$http'];

function testService($http) {
   return { 
        getTestDatas: function (callback) {
        var data = $.param({ // $.param for jsfiddle
            json: JSON.stringify({ // json wrapper just for jsfiddle
                testParams: 'test'
            }),
            delay: 1
        });

        return $http.post('/echo/json/', data)
            .success(function (response) {
                console.log(response);
                callback ? callback(response): undefined;
            });
        },
    };
};

function MainCtrl($scope, testService) {
    
    var getDataCb = function(response) {
        $scope.data = response;
    };
    
    testService.getTestDatas(getDataCb);
    
}

MainCtrl.$inject = ['$scope', 'testService'];

// specs code
describe("Test suite for $http service", function() {
  
  var $httpBackend, $rootScope, $testService;

   // Set up the module
   beforeEach(module('web.template'));

   beforeEach(inject(function($injector) {
     // Set up the mock http service responses
     $httpBackend = $injector.get('$httpBackend');
     // backend definition common for all tests
     var fakedMainResponse = {testParams: 'testMocked' };
     $httpBackend.when('POST', '/echo/json/').respond(fakedMainResponse);
     //authRequestHandler = $httpBackend.when('GET', '/echo/json/')
     //                       .respond({testParams: 'testMocked' });

     $testService = $injector.get('testService');
     // Get hold of a scope (i.e. the root scope)
     $rootScope = $injector.get('$rootScope');
     // The $controller service is used to create instances of controllers
     //var $controller = $injector.get('$controller');

     //createController = function() {
     //  return $controller('MyController', {'$scope' : $rootScope });
     //};
   }));


   afterEach(function() {
     $httpBackend.verifyNoOutstandingExpectation();
     $httpBackend.verifyNoOutstandingRequest();
   });
    
  it("server should return test value with callback", function() {
      
    //expect(true).toBe(false);
      $testService.getTestDatas(function(response) {
          console.log('testing service', response);
          expect(response).toEqual({"testParams": "testMocked"});
          //expect(true).toBe(false);
      });
      $httpBackend.flush();
  });
    
  it("server should return test value with promise", function() {
      
    //expect(true).toBe(false);
      $testService.getTestDatas(undefined).then(function(response) {
          expect(response.data).toEqual({"testParams": "testMocked"});
      });
      $httpBackend.flush();
  });

});

// load jasmine htmlReporter
(function() {
  var env = jasmine.getEnv();
  env.addReporter(new jasmine.HtmlReporter());
  env.execute();
}());
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.16/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.16/angular-mocks.js"></script>
<script src="http://code.jquery.com/jquery-1.11.3.js"></script>
<script src="http://cdn.jsdelivr.net/jasmine/1.3.1/jasmine.js"></script>
<script src="http://cdn.jsdelivr.net/jasmine/1.3.1/jasmine-html.js"></script>
<link href="http://cdn.jsdelivr.net/jasmine/1.3.1/jasmine.css" rel="stylesheet"/>
<div ng-app="web.template" ng-controller="mainCtrl"><pre>{{data|json}}</pre></div>