Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jasmine test case error 'Spy to have been called'

I'm writing jasmine test case for below angular function and getting test case failed message "Expected spy [object Object] to have been called".

    $scope.displayTagModelPopup = function() {
        var dialogOptions = {
            templateUrl: 'views/mytags.html',
            controller: 'TagsCtrl',
            size: 'lg',
            resolve: {
                tagsAvailable: function() {
                    return $scope.availableTags;
                }
            }
        };

        ModalDialogFactory.showDialog(dialogOptions).then(function(result) {
            $scope.selectedFields = [];
            $scope.selectedFieldIds = [];

            angular.forEach(result, function(tag) {
                $scope.selectedFields.push(tag);
                $scope.selectedFieldIds.push(tag.objectId);
            });
        });
    };

My Jasmine Test case

it('should call displayTagModelPopup', function() {
    var dialogOptions = {
        templateUrl: 'views/mytags.html',
        controller: 'TagsCtrl',
        size: 'lg',
        tagsAvailable: [{
            objectId: "c647abc7-f651-4df6-880d-cf9fb69cdcb0",
            dataFieldName: "author",
            shortNamePath: "$.author",
            templates: ["HaM sheet"]
        }]
    };
    var spy = jasmine.createSpy(modalDialogFactory, 'showDialog').and.callFake(function(data) {
        $scope.tags = [{
            objectId: "c647abc7-f651-4df6-880d-cf9fb69cdcb0",
            dataFieldName: "author",
            shortNamePath: "$.author",
            templates: ["HaM sheet"]
        }];
        return $scope.tags;
    });

    $scope.displayTagModelPopup();
    $scope.$digest();
    expect(spy).toHaveBeenCalled();

});

And getting the below error "Expected spy [object Object] to have been called. Error: Expected spy [object Object] to have been called."

what is the issue in my test case?am i missing anything?

Thanks in Advance!!!

Edited: Changed my Jasmine test case like below getting different message ''undefined' is not a function (evaluating 'ModalDialogFactory.showDialog(dialogOptions).then')'

Tried whether ModelDialogFactory is defined or not but ModalDialogFactory.showDialog method is defined successfully. getting test case failed only when call the method '$scope.displayTagModelPopup();'

it('should call displayTagModelPopup', function() {

    spyOn(ModalDialogFactory, 'showDialog').and.callFake(function() {
        $scope.tags = [{
            objectId: "c647abc7-f651-4df6-880d-cf9fb69cdcb0",
            dataFieldName: "author",
            shortNamePath: "$.author",
            templates: ["HaM sheet"]
        }];
        return $scope.tags;
    });
    var dialogOptions = {
        templateUrl: 'views/mytags.html',
        controller: 'TagsCtrl',
        size: 'lg',
        tagsAvailable: [{
            objectId: "c647abc7-f651-4df6-880d-cf9fb69cdcb0",
            dataFieldName: "author",
            shortNamePath: "$.author",
            templates: ["HaM sheet"]
        }]
    };
    //expect(ModalDialogFactory).toBeDefined();
    //expect(ModalDialogFactory.showDialog).toBeDefined();

    $scope.displayTagModelPopup();
    $scope.$digest();

});
like image 507
Prabaharan Kathiresan Avatar asked Jul 26 '15 07:07

Prabaharan Kathiresan


1 Answers

If you want to spy on a method of existing object you should use spyOn helper (docs):

spyOn(modalDialogFactory, 'showDialog').and.callFake(...);

As a first parameter it applies an object, and as the second - name of the method. It replaces an existing object's method with a spy object.

To check if spy was called you should pass it to expect():

expect(modalDialogFactory.showDialog).toHaveBeenCalled();

The helper you use jasmine.createSpy() is to create a "bare" spy, which could be passed as a callback to ensure it will be called (docs). jasmine.createSpy() only applies one parameter which is the name of the spy to be shown in test results, this is why there is no any spy attached to your object.


Update:

You have a line in the first snippet:

ModalDialogFactory.showDialog(dialogOptions).then(function(result) { ... });

and as you can see showDialog() is followed by then(). I assume that original showDialog() returns some object with a method then(), maybe it's a Promise. But in your test when you spy on a showDialog() method, from callFake() you do not return anything with then() method, therefore the error states that a method is undefined. Spy completely replaced your original method and in conjunction with callFake() it recreates original behavior.

So from callFake() you should return something that imitates a Promise, for example:

spyOn(ModalDialogFactory, 'showDialog').and.callFake(function() {
    // ....
    return {
        then: function (cb) {
             cb($scope.tags);
        }
    };
});

Here I return an object which has then() method, and when it's called with a function as a parameter, then this function acting like a callback is resolved with a $scope.tags value, which could be used inside this callback.

like image 157
Michael Radionov Avatar answered Oct 22 '22 19:10

Michael Radionov