简体   繁体   中英

Testing Angular Service resolve promise in error callback

I am trying to figure out how to test the 403 response in the following code. The code works as expected. I realized using 403 is not the best option here but that is out of my control right now and I cant change it. I am new to JS testing an feel like I am missing something and have reached the end of my knowledge. Any help would be appreciated.

  this.joinItem = function(item, joinOption) {
  var deferred = $q.defer(),
      joinUrl = ('http://testurl.com/company/items/abc456/join', joinData),
      joinData = {
        match: {
          minid: joinOption['id']
        }
      };

  $http.post(joinUrl, joinData, { headers: headers })
    .success(handleJoinSuccess)
    .error(handleJoinError);

  function handleJoinSuccess() {
    deferred.resolve({status: 204});
    };

  function handleJoinError(joinedResponse, status) {
    var joinedItems = joinedResponse['joined_items'];
    if (status === 403) {
      deferred.resolve({
        joinedItems: joinedItems,
        status: status
      });
    } else {
      deferred.reject({
        status: status
      });
    }
  }

  return deferred.promise;
};

Here is the test I have so far. I have no idea how to get this promise to resolve. I may have more crap in this test than needed but I am so lost right now I have no idea.

   describe('itemService', function () {
   'use strict';

   var subject;

   beforeEach(inject(function (_itemService_) {
     subject = _itemService_;
   })); 

 describe('#joinItem 403', function () {
 var $httpBackend,
    $rootScope,
    deferred,
    item,
    joinOption,
    joinData,
    joinedResponse,
    joinRequest,
    joinedItemsResults,
    joinedItems;

beforeEach(inject(function(_$httpBackend_, $q, _$rootScope_) {
  $httpBackend = _$httpBackend_;
  $rootScope = _$rootScope_;
  deferred = $q.defer();
  item = { id: 'abc456' };
  joinOption = { id: 'optID' };
  joinData = { match: { minid: 'optID' } };
  joinedResponse = { 'joined_products': []};
  joinRequest = $httpBackend.whenPOST('http://testurl.com/company/items/abc456/join', joinData).respond(403);
  joinedItemsResults = { joined_products: [], status: 403 };
}));

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

describe('when request completes with 403 status', function () {
  it('resolves the promise', function () {
    var handler = jasmine.createSpy('error');
    var promise = subject
      .joinItem(item, joinOption);
    promise.then(handler);
    deferred.resolve(joinedResponse);
    $rootScope.$digest();
    $httpBackend.flush();

    expect(promise).toBeResolvedWith(joinedItemsResults);
  }); 
}); 

I have setup a jsfiddle for your problem. In the test I have simplified your POST url. Something to notice :

  1. You should return data response(Because you do that in your real service) when expectPOST from $httpBackend . Ex :

     $httpBackend.whenPOST('/path/to/your/url') .respond(403, yourErrorResponseData); 
  2. Because $http already return a promise, so you dont need to return defer.promise

  3. In your test, you can test the data that you return in $httpBackend by using promise. And dont forget to call $httpBackend.flush to flush request.

     myService.joinItem(item, joinOption).then(function (data) { expect(data).toEqual(joinedItemResults); }); $httpBackend.flush(); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM