Unit test service that returns promise Angularjs Jasmine

Mdb

EDITED per Michal Charemza post.

I have a service that represents angularui modal dialog:

app.factory("dialogFactory", function($modal, $window, $q) {

    function confirmDeleteDialog() {

    var modalInstance = $modal.open({
        templateUrl: "../application/factories/confirmDeleteDialog.htm",
        controller: function($scope, $modalInstance) {

            $scope.ok = function() {
                $modalInstance.close("true");
            };

            $scope.cancel = function() {
                $modalInstance.dismiss("false");
            };
        }
    });


    return modalInstance.result.then(function(response) {
        return 'My other success result';
    }, function(response) {
        return $q.reject('My other failure reason');
    });

};

    return {
        confirmDeleteDialog: confirmDeleteDialog
    };

});

On calling the delete method if the user has clicked Ok from the dialog requestNotificationChannel.deleteMessage(id) is executed.

$scope.deleteMessage = function(id) {
        var result = dialogFactory.confirmDeleteDialog();

        result.then(function(response) {
            requestNotificationChannel.deleteMessage(id);
        });
    };

The problem is I am not able to unit test this.

This is my test. I have correctly injected the q service but I am not sure what should I return from "confirmDeleteDialog" spy...

describe("has a delete method that should call delete message notification", function() {
            var deferred = $q.defer();
            spyOn(dialogFactory, "confirmDeleteDialog").and.returnValue(deferred.promise);

            spyOn(requestNotificationChannel, "deleteMessage");

            $scope.deleteMessage(5);
            deferred.resolve();

            it("delete message notification is called", function() {
                expect(requestNotificationChannel.deleteMessage).toHaveBeenCalled();
            });
        });

But I am receiving expected spy deleteMessage to have been called. Which means that the result.then... part is not executed. What am I missing ?

Michal Charemza

To mock a function that returns a promise, it will need to also return a promise, which then needs to be resolved as a separate step.

In your case the deferred.resolve() you pass to the spy needs to be replaced with deferred.promise, and the deferred.resolve() performed separately.

beforeEach(function() {
  var deferred = $q.defer();
  spyOn(dialogFactory, "confirmDeleteDialog").and.returnValue(deferred.promise);
  spyOn(requestNotificationChannel, "deleteMessage");
  $scope.deleteMessage(5);
  deferred.resolve();
  $rootScope.$digest();
});

it("delete message notification is called", function() {
  expect(requestNotificationChannel.deleteMessage).toHaveBeenCalled();
});

I suspect you also need to call $rootScope.$digest(), as Angular's promise implementation is tied to the digest loop.

Also, slightly unrelated to your question, but I don't think you need to create your own deferred object in confirmDeleteDialog. The (anti) pattern you're using has been labelled 'The Forgotten Promise', as in http://taoofcode.net/promise-anti-patterns/

When is simpler, uses less code, and I think that allows better error handling, you can just return the promise that the $modal service creates:

var modalInstance = $modal.open({...});
return modalInstance.result;

If you want to modify what the calling function sees, in terms of resolved/rejected values, you can create a chained promise by returning the result of then:

var modalInstance = $modal.open({...});
return modalInstance.result.then(function(successResult) {
  return 'My other success result';
}, function(failureReason) {
  return $q.reject('My other failure reason');
});

You would usually want to do this if you don't want to expose the inner-workings of a function to its caller. This is analogous to the concept of re-throwing an exception in synchronous programming.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Unit test service that returns promise Angularjs Jasmine

From Java

How do I mock a service that returns promise in AngularJS Jasmine unit test?

From Dev

How to test with Jasmine an AngularJS controller that calls service method that returns promise

From Dev

How to unit test (using Jasmine) a function in a controller which calls a factory service which returns a promise

From Dev

AngularJS Controller As Jasmine test with mock service with promise

From Dev

Jasmine unit testing angular service that returns promise doesn't resolve

From Dev

Jasmine/AngularJS: Inject dependent service to service in unit test?

From Dev

Jasmine, AngularJS: Unit test a function which returns a value after timeout

From Dev

How can I test what an AngularJS promise returns using Jasmine?

From Dev

How can I test what an AngularJS promise returns using Jasmine?

From Dev

AngularJS Service Jasmine Unit Test Unflushed Request Error

From Dev

AngularJS Service Jasmine Unit Test Unflushed Request Error

From Dev

angularjs unit test promise based service (SQlite database service)

From Dev

How to test that my service returns data with jasmine and angularjs

From Dev

$httpBackend in AngularJs Jasmine unit test

From Dev

AngularJS controller unit test with Jasmine

From Dev

Angularjs Unit Test for Service

From Dev

Test AngularJS service that returns a promise without calling $rootScope.$apply()?

From Dev

Angularjs unit testing service with promise

From Dev

Angularjs Unit Test Not Hitting then part of controller after calling service in AngularJS & testing using Karma & Jasmine

From Dev

Angularjs Unit Test Not Hitting then part of controller after calling service in AngularJS & testing using Karma & Jasmine

From Dev

Jasmine unit test AngularJS factory with two dependencies ($http and another factory returning promise)

From Dev

Angular and Jasmine: how to mock a service that returns a promise

From Dev

Jasmine test for an ajax request that returns a promise

From Dev

Jasmine Unit Test, override only property in service

From Dev

Jasmine Unit Test, override only property in service

From Dev

mock angularjs service for unit testing using jasmine

From Dev

mock angular service/promise in a karma/jasmine test

From Dev

Jasmine unit test case for $routeChangeStart in AngularJS

Related Related

  1. 1

    Unit test service that returns promise Angularjs Jasmine

  2. 2

    How do I mock a service that returns promise in AngularJS Jasmine unit test?

  3. 3

    How to test with Jasmine an AngularJS controller that calls service method that returns promise

  4. 4

    How to unit test (using Jasmine) a function in a controller which calls a factory service which returns a promise

  5. 5

    AngularJS Controller As Jasmine test with mock service with promise

  6. 6

    Jasmine unit testing angular service that returns promise doesn't resolve

  7. 7

    Jasmine/AngularJS: Inject dependent service to service in unit test?

  8. 8

    Jasmine, AngularJS: Unit test a function which returns a value after timeout

  9. 9

    How can I test what an AngularJS promise returns using Jasmine?

  10. 10

    How can I test what an AngularJS promise returns using Jasmine?

  11. 11

    AngularJS Service Jasmine Unit Test Unflushed Request Error

  12. 12

    AngularJS Service Jasmine Unit Test Unflushed Request Error

  13. 13

    angularjs unit test promise based service (SQlite database service)

  14. 14

    How to test that my service returns data with jasmine and angularjs

  15. 15

    $httpBackend in AngularJs Jasmine unit test

  16. 16

    AngularJS controller unit test with Jasmine

  17. 17

    Angularjs Unit Test for Service

  18. 18

    Test AngularJS service that returns a promise without calling $rootScope.$apply()?

  19. 19

    Angularjs unit testing service with promise

  20. 20

    Angularjs Unit Test Not Hitting then part of controller after calling service in AngularJS & testing using Karma & Jasmine

  21. 21

    Angularjs Unit Test Not Hitting then part of controller after calling service in AngularJS & testing using Karma & Jasmine

  22. 22

    Jasmine unit test AngularJS factory with two dependencies ($http and another factory returning promise)

  23. 23

    Angular and Jasmine: how to mock a service that returns a promise

  24. 24

    Jasmine test for an ajax request that returns a promise

  25. 25

    Jasmine Unit Test, override only property in service

  26. 26

    Jasmine Unit Test, override only property in service

  27. 27

    mock angularjs service for unit testing using jasmine

  28. 28

    mock angular service/promise in a karma/jasmine test

  29. 29

    Jasmine unit test case for $routeChangeStart in AngularJS

HotTag

Archive