3

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?

Community
  • 1
  • 1
faizanjehangir
  • 2,771
  • 6
  • 45
  • 83

1 Answers1

2

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"]);
})
Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
  • solution works perfectly! However, do you mind explaining how the test case is executed? As `httpbackend success` response will always be equal to the `expected data`? In other words, how (am I/should I) testing the `response` returned from service `promise`? – faizanjehangir Apr 27 '16 at 15:58