【问题标题】:How to test if method has been called only once and not the second time in Jasmine?如何测试方法是否在 Jasmine 中只被调用过一次而不是第二次?
【发布时间】:2014-06-11 09:47:08
【问题描述】:

我正在测试应该调用一次方法并防止使用 jasmine 进行任何后续调用的机制,我可以通过附加断点看到该方法没有被第二次调用,但是 jasmine 测试失败。我认为这与 spy 未设计用于多次检查有关。
对于特定情况,什么是适当的解决方案?

JSfiddle of Code that is being tested我不知道如何正确地进行 jasmine 测试 jsfiddle(我使用的 Jasmine 版本是 1.3.1,而测试模板是 1.2.0)。

测试如下:

 it("Invoking OnPreQuery will add event listener for OnTheMoveViewPreLoad event. Triggering OnTheMoveViewPreLoad twice will call getChildrenForMasterRecordList only first time", function () {
            AddTreeSettingsObjectToBC({ bc: bc, Tree: { IncludeChildren: true} });
            ComposeMockPageObjWithObservableFieldsWithChildren();
            var preQuerySpy = spyOnEvent(onTheMove.PageDataRoles, 'OnPreQuery');
            $(onTheMove.PageDataRoles).trigger('OnPreQuery', { knockoutContextName: 'bc' });
            expect('OnPreQuery').toHaveBeenTriggeredOn(onTheMove.PageDataRoles);
            expect(preQuerySpy).toHaveBeenTriggered();
            var getChildrenForMasterRecordListSpy = spyOn(window, 'getChildrenForMasterRecordList');
            $(onTheMove.PageDataRoles).trigger('OnTheMoveViewPreLoad', { knockoutContextName: 'bc' });
            expect(getChildrenForMasterRecordListSpy).toHaveBeenCalled();
            $(onTheMove.PageDataRoles).trigger('OnTheMoveViewPreLoad', { knockoutContextName: 'bc' });
            expect(getChildrenForMasterRecordListSpy).not.toHaveBeenCalled();
        });

正在测试的代码: HTML

<div data-role="page"></div>

Javascript

var onTheMove = function(){};
$.extend(onTheMove,{
    NullValue : "null",
    PageDataRoles : 'div[data-role="page"], div[data-role="dialog"]',
    OnTheMovePrefix : 'OnTheMove_'
    });

$(document).on('OnPreQuery', onTheMove.PageDataRoles, function (e, options) {
    var isChildAttachmentQueued = true;
    var knockoutContextName = options.knockoutContextName;
    if (TreeEnabled(knockoutContextName)) {
        var isModelReadyToAttachChildren = function () {
            var isReady = false;
            if (PageObj[knockoutContextName] != undefined) {
                isReady = (PageObj[knockoutContextName]().length > 0) && isChildAttachmentQueued;
            }

            return isReady;
        };
        var treeSettings = eval(knockoutContextName).Tree;
        treeSettings.knockoutContextName = knockoutContextName;
        $(onTheMove.PageDataRoles).on('OnTheMoveViewPreLoad', function (e, options) {
            if (isModelReadyToAttachChildren()) {
                getChildrenForMasterRecordList({
                    parentTable: eval(knockoutContextName).primaryTableName,
                    knockoutContextName: treeSettings.knockoutContextName,
                    parentIdColumn: treeSettings.ParentIdColumn,
                    masterIdColumn: treeSettings.MasterIdColumn
                });
                isChildAttachmentQueued = false;
            }
        });
    }
});
function getChildrenForMasterRecordList(options) {
    console.log('beep');
}

【问题讨论】:

    标签: javascript jquery testing knockout.js jasmine


    【解决方案1】:

    我自己想通了,spy 有 callCount 属性,每次调用都会自动递增 1。

        it("Invoking OnPreQuery will add event listener for OnTheMoveViewPreLoad event. Triggering OnTheMoveViewPreLoad twice will call getChildrenForMasterRecordList only first time", function () {
            AddTreeSettingsObjectToBC({ bc: bc, Tree: { IncludeChildren: true} });
            ComposeMockPageObjWithObservableFieldsWithChildren();
            var preQuerySpy = spyOnEvent(onTheMove.PageDataRoles, 'OnPreQuery');
            $(onTheMove.PageDataRoles).trigger('OnPreQuery', { knockoutContextName: 'bc' });
            expect('OnPreQuery').toHaveBeenTriggeredOn(onTheMove.PageDataRoles);
            expect(preQuerySpy).toHaveBeenTriggered();
            var getChildrenForMasterRecordListSpy = spyOn(window, 'getChildrenForMasterRecordList');
            $(onTheMove.PageDataRoles).trigger('OnTheMoveViewPreLoad', { knockoutContextName: 'bc' });
            expect(getChildrenForMasterRecordListSpy).toHaveBeenCalled();
            $(onTheMove.PageDataRoles).trigger('OnTheMoveViewPreLoad', { knockoutContextName: 'bc' });
            expect(getChildrenForMasterRecordListSpy.callCount).toEqual(1);
        });
    

    根据评论

    在 Jasmine 2.0 中

    expect(object.func.calls.count()).toBe(1);
    

    【讨论】:

    • 在 jasmine 2.0 中,这一点略有改变。您现在检查 calls.count()... 例如:expect(object.func.calls.count()).toBe(1);
    【解决方案2】:

    toHaveBeenCalledTimes(1)

    现在让这变得容易多了。

     expect(yourSpy).toHaveBeenCalledTimes(1);
    

    【讨论】:

    • 谢谢。我还能找出每个调用使用的参数吗?
    • 当然。试试.toHaveBeenCalledWith("yourArgument")
    • 对不起,我很困惑。如果一个间谍被调用两次,第一次调用的参数为 1,第二次调用的参数为 2,我如何检查 (a) 间谍被调用了两次 (b) 第一次调用是使用参数 1 (c) 第二次调用是使用参数 2?
    • 根据您的功能的复杂性,您可能需要单独检查它们。这样,如果它失败了,你就知道为什么了。像这样: 1. 检查你的函数是否被调用了两次,使用.toHaveBeenCalledTimes(2) 2. 检查你的函数是使用参数1调用的,使用toHaveBeenCalledWith("argument 1") 3. 检查你的函数是使用参数2调用的,使用toHaveBeenCalledWith("argument 2")如果您想检查 order,这可能有点棘手。您也许可以深入研究 spy 对象并检查每个调用的数组位置。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-13
    • 1970-01-01
    • 2022-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多