Darwin Tech
Darwin Tech

Reputation: 18929

Test an Angularjs service which makes API calls

I have a Service which contains my code for making async API calls:

myApp.factory('ConcernService', function ($http, $q, $rootScope, dateFilter, globals) {

  var api_url = 'http://' + globals.site_url + '/api/';

  var ConcernService = {

    list: function (items_url) {
      var defer = $q.defer();
      $http({method: 'GET', 
        url: api_url + items_url}).
        success(function (data, status, headers, config) {
          defer.resolve(data);
        }).error(function (data, status, headers, config) {
          defer.reject(status);
        });
      return defer.promise;
    },
    ...
  };
});

I am trying to write a Jasmine test for this method, but it is proving tricky as I am new to both Angular and Jasmine.

So far my test looks like so:

describe('$http basic', function () {

  var $http, $httpBackend, $scope;
  beforeEach(module('concernsApp'));
  beforeEach(inject(function (_ConcernService_, _$http_, _$httpBackend_) {
    ConcernService = _ConcernService_;
    $http = _$http_;
    $httpBackend = _$httpBackend_;
  }));

  it('should return all projects', function () {

      var projects = [{"id": 2, "title": "FooProject", "created_by": 1}, {"id": 5, "title": "BarProject", "created_by": 1}];

      $httpBackend.whenGET('http://localhost:8000/api/projects/')
        .respond(projects);

      ConcernService.list('projects')
        .then(function(data) {
          console.log('data', data);
          expect(data.length).toEqual(2);
      });

      $httpBackend.flush();
  });
});

This is failing, but I'm not entirely sure why.

Upvotes: 1

Views: 1344

Answers (1)

Darwin Tech
Darwin Tech

Reputation: 18929

So, it turns out the error was because promises are being used, which means that the apply() methods needs to be used before $httpBackend.flush();. I also, as JB Nizet rightly pointed out, had an an inconsistency in my url structure, which revealed itself when the initial problem was addressed.

The working code:

describe('$http basic', function () {

  var $http, $httpBackend, $scope;
  beforeEach(module('concernsApp'));
  beforeEach(inject(function ($rootScope, _ConcernService_, _$httpBackend_) {
    ConcernService = _ConcernService_;
    $httpBackend = _$httpBackend_;
    $scope = $rootScope.$new();
  }));

  it('should return all projects', function () {
      var projects = [{"id": 2, "title": "FooProject", "created_by": 1}, {"id": 5, "title": "BarProject", "created_by": 1}];

      $httpBackend.whenGET('http://localhost:8000/api/projects')
        .respond(projects);

      ConcernService.list('projects')
        .then(function(data) {
          expect(data.length).toEqual(2);
      });

      $scope.$apply();
      $httpBackend.flush();
  });
});

Upvotes: 1

Related Questions