faizanjehangir
faizanjehangir

Reputation: 2829

service promise not resolving with karma

I have a service factory that connects and interacts with an api for data. Here is the service:

angular.module('dbRequest', [])
  .factory('Request', ['$http', 'localConfig', function($http, localConfig){
    return {
      getDataRevision: function(){
        return $http({
          url: localConfig.dbDataUrl,
          method: "GET",
          crossDomain: true,
          headers: {
            'Content-Type': 'application/json; charset=utf-8'
          }
        })
      }
    }
  }]);

Taking cues from this answer, This is how I am testing the method:

describe('Service: Request', function () {
  var $scope, srvMock, $q, lc, $httpBackend;

  beforeEach(module('webApp'));

  beforeEach(inject(function($rootScope, Request, _$q_, _$httpBackend_, localConfig){
    $scope = $rootScope.$new();
    srvMock = Request;
    $q = _$q_;
    $httpBackend = _$httpBackend_;
    lc = localConfig;

    $httpBackend.expect('GET', lc.dbDataUrl);

    $httpBackend.when('GET', lc.dbDataUrl).respond({
      success: ["d1","d2", "d3"]
    });
  }));

  it('should return a promise', function(){
    expect(srvMock.getDataRevision().then).toBeDefined();
  });

  it('should resolve with data', function(){
    var data;
    var deferred = $q.defer();
    var promise = deferred.promise;

    promise.then(function(res){
      data = res.success;
    });

    srvMock.getDataRevision().then(function(res){
      deferred.resolve(res);
    });

    $scope.$digest();

    expect(data).toEqual(["d1","d2", "d3"]);
  })
});

should return a promise passes, but the next should resolve with data fails with this error:

Expected undefined to equal [ 'd1', 'd2', 'd3' ].

However, the service method getDataRevision is getting called, but not getting resolved by the mock promise in the test. How do I make the correction?

Upvotes: 3

Views: 524

Answers (1)

Pankaj Parkar
Pankaj Parkar

Reputation: 136144

Currently you are expecting mocked data to be there in data variable without flushing httpRequests, but that won't happen till you flush all the httpRequests. What $httpBackend.flush() does is, it returns mock data to that particular request that you have did using $httpBackend.when('GET', lc.dbDataUrl).respond.

Additionally you don't need to create extra promise which would be an overhead. Instead of having custom promise you could have utilize service function returned promise itself like below.

Code

it('should resolve with data', function(){
    var data;

    srvMock.getDataRevision().then(function(res){
      data = res.success;
    });

    $scope.$digest();
    $httpBackend.flush(); //making sure mocked response has been return
    //after .then evaluation only below code will get called.
    expect(data).toEqual(["d1","d2", "d3"]);
})

Upvotes: 2

Related Questions