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 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

Jasmine unit test case for $routeChangeStart in AngularJS

From Dev

mock angularjs service for unit testing using jasmine

From Dev

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

From Dev

mock angular service/promise in a karma/jasmine test

From Dev

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

From Dev

AngularJS controller unit test with Jasmine

From Dev

Jasmine test for an ajax request that returns a promise

From Dev

$httpBackend in AngularJs Jasmine unit test

From Dev

AngularJS Controller As Jasmine test with mock service with promise

From Dev

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

From Dev

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

From Dev

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

From Dev

Angularjs unit testing service with promise

From Dev

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

From Dev

AngularJS Service Jasmine Unit Test Unflushed Request Error

From Dev

Jasmine Unit Test, override only property in service

From Dev

angularjs unit test promise based service (SQlite database service)

From Dev

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

From Dev

Jasmine Unit Test, override only property in service

From Dev

Angularjs Unit Test for Service

From Dev

Unit test service that returns promise Angularjs Jasmine

From Dev

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

From Dev

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

From Dev

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

From Dev

AngularJS Service Jasmine Unit Test Unflushed Request Error

From Dev

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

From Dev

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

Related Related

  1. 1

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

  2. 2

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

  3. 3

    Jasmine unit test case for $routeChangeStart in AngularJS

  4. 4

    mock angularjs service for unit testing using jasmine

  5. 5

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

  6. 6

    mock angular service/promise in a karma/jasmine test

  7. 7

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

  8. 8

    AngularJS controller unit test with Jasmine

  9. 9

    Jasmine test for an ajax request that returns a promise

  10. 10

    $httpBackend in AngularJs Jasmine unit test

  11. 11

    AngularJS Controller As Jasmine test with mock service with promise

  12. 12

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

  13. 13

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

  14. 14

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

  15. 15

    Angularjs unit testing service with promise

  16. 16

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

  17. 17

    AngularJS Service Jasmine Unit Test Unflushed Request Error

  18. 18

    Jasmine Unit Test, override only property in service

  19. 19

    angularjs unit test promise based service (SQlite database service)

  20. 20

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

  21. 21

    Jasmine Unit Test, override only property in service

  22. 22

    Angularjs Unit Test for Service

  23. 23

    Unit test service that returns promise Angularjs Jasmine

  24. 24

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

  25. 25

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

  26. 26

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

  27. 27

    AngularJS Service Jasmine Unit Test Unflushed Request Error

  28. 28

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

  29. 29

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

HotTag

Archive