Javascript Jasmine 测试用例错误“间谍已被调用”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31634863/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 06:57:50  来源:igfitidea点击:

Jasmine test case error 'Spy to have been called'

javascriptangularjsjasminekarma-jasmine

提问by Prabaharan Kathiresan

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

我正在为下面的 angular 函数编写 jasmine 测试用例,并收到测试用例失败消息“预期的间谍 [对象对象] 已被调用”。

    $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')'

编辑:改变了我的茉莉花测试用例,如下所示得到不同的消息“未定义”不是一个函数(评估“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();'

尝试是否定义了 ModelDialogFactory 但 ModalDialogFactory.showDialog 方法定义成功。仅在调用方法“$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();

});

回答by Michael Radionov

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

如果您想监视现有对象的方法,您应该使用spyOnhelper ( 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():

要检查是否调用了 spy,您应该将其传递给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 (createSpyObj" rel="nofollow">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.

您使用的助手jasmine.createSpy()是创建一个“裸”间谍,它可以作为回调传递以确保它会被调用(createSpyObj" rel="nofollow">docs)。jasmine.createSpy()只应用一个参数,即要在测试结果中显示的间谍的名称,这就是为什么没有任何间谍附加到您的对象。



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.

正如你所看到的showDialog(),后面跟着then(). 我假设 originalshowDialog()返回一些带有方法的对象then(),也许它是一个 Promise。但是在您的测试中,当您监视showDialog()方法时,callFake()您不会使用then()方法返回任何内容,因此错误表明方法未定义。Spy 完全取代了您的原始方法,并结合callFake()它重新创建了原始行为。

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

所以callFake()你应该返回一些模仿 Promise 的东西,例如:

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.tagsvalue, which could be used inside this callback.

在这里,我返回一个具有then()方法的对象,当它以一个函数作为参数被调用时,这个函数就像一个回调函数$scope.tags,它用一个值解析,这个值可以在这个回调函数中使用。