Kratos
Kratos

Reputation: 1114

Testing if a promise is called from a controller unit-testing AngularJS

I am writing unit tests in AngularJS using karma and I would like to test the following controller whether is calling or not the service. I cant use spyOn because it is a promise and not a function. I don't want to test the service itself but I can't figure out how can I do it.

    $scope.deleteItem= function(itemId){
    service.deleteItem(itemId)
    .then(function(){
      $scope.info("Deleted");
      $scope.getData();
    }, function(data){
      $scope.critical('error');
    });
};

Upvotes: 1

Views: 515

Answers (1)

Jon Quarfoth
Jon Quarfoth

Reputation: 2129

Without more context, I'm not seeing why spyOn wouldn't work. It should. The fact that deleteItem returns a promise doesn't prevent you from using spyOn to spy on the deleteItem function. You should be using spyOn to replace the deleteItem function with a spy, and any value you return with the spy should be a promise.

There may be an issue with with how you're injecting the service into the controller in the test. You would have to post some of your test code to determine if this is the case.

If you have a reference to the service dependency in your test, you should be able to use spyOn to spy on the deleteItem method. Then you just need to provide an appropriate promise as the return value.

To simulate a resolved promise:

spyOn(service, 'deleteItem').and.returnValue($q.when(value));

To simulate a rejected promise:

spyOn(service, 'deleteItem').and.returnValue($q.reject(value));

And in most cases, you'll need a manual call to $rootScope.$digest() somewhere in the test to let the angular lifecycle know it's time to resolve the promise.

After the $rootScope.$digest(), you can verify that your controller took the proper actions when the promise was resolved (or rejected).

it('controller.deleteItem() should do stuff after service.deleteItem completes successfully', function() {
    var controller = createController();
    spyOn(service, 'deleteItem').and.returnValue($q.when());
    controller.deleteItem('id');

    //Tell Angular to resolve the promise
    $rootScope.$digest();

    // Verify that the controller is in correct state now that promise is resolved
    // i.e. expect(something).toEqual(somethingElse);
});

Upvotes: 5

Related Questions