Kratos
Kratos

Reputation: 1114

Functions in promise not called in unit-testing karma

The following test for the following function always succeeds because it never calls any of the "then", "catch" or "finally" functions.

function:

getItems: function() {
    return $http.get(serviceRoot+'/getItems/'+idService.id()).then(function(response) {
      return commonService.validateServerJson(response.data.options);
    })
  },

The test:

it('should get items',function(done) {
    spyOn(commonService, 'validateServerJson').andCallThrough();
    spyOn(idService, 'id').andCallThrough();
    itemsService.getItems().then(function(response) {
        expect(response.value).toEqual("fff");
        expect(commonService.validateServerJson).toHaveBeenCalled();
        expect(idService.id).toHaveBeenCalled();
    }).catch( function(response) {
        expect(false).toEqual(true);
    }).finally(done);

});

Upvotes: 1

Views: 501

Answers (1)

Jon Quarfoth
Jon Quarfoth

Reputation: 2129

You'll need to use $httpBackend to make sure that your $http promise gets resolved.

You may also need to manually invoke the AngularJS lifecycle to make sure that the promise you're chaining off the $http call resolves.

I'd advise using done.fail('message') instead of expect(false).toEqual(true) and get a better report of what happened. This also removes the finally from the picture, simplifying the test.

Does this work any better?

it('should get items', function(done) {
    var mockHttpResponse = { /* INSERT EXPECTED HTTP RESPONSE */};
    $httpBackend.when('GET', 'INSERT/EXPECTED/PATH/HERE').respond(mockHttpResponse);
    spyOn(commonService, 'validateServerJson').andCallThrough();
    spyOn(idService, 'id').andCallThrough();
    itemsService.getItems().then(function(response) {
        expect(response.value).toEqual("fff");
        expect(commonService.validateServerJson).toHaveBeenCalled();
        expect(idService.id).toHaveBeenCalled();
        done();
    }, function(){
        done.fail('getItems() promise was rejected');
    });
    $httpBackend.flush(); //Resolve $http promise
    $rootScope.$digest(); //Force AngularJS lifecycle to run and resolve other promises.
});

Upvotes: 1

Related Questions