【问题标题】:Testing return value of spied methods using Jasmine使用 Jasmine 测试间谍方法的返回值
【发布时间】:2012-05-04 11:15:43
【问题描述】:

完全披露...这是我的第一个 SO 问题。如果我遗漏任何内容,请善待。 ;-)

我开始使用Jasmin 来测试我的一个客户端Javascript 对象。该对象特别管理名为DataTables 的jQuery 插件的使用。托管的 DataTables 组件将调用几个自定义呈现方法来确定为几列显示什么,我正在尝试测试这些方法。

简短的问题:如何测试我需要设置间谍的方法的返回值?

背景故事

这是我的 Javascript 对象的缩小版:

function Table(elemId) {
    this._table = $('#'+elemId).dataTable({
        "aoColumnDefs": [
            {
                "fnRender": function(oObj, id) { 
                    return Table.renderIdColumn(oObj, id, lTable); 
                }, 
                "aTargets": ["idColumn"], 
                "bUseRendered": false
            },{
                "fnRender": function(oObj, name) { 
                    return Table.renderNameColumn(oObj, name, lTable); 
                }, 
                "aTargets": ["nameColumn"], 
                "bUseRendered": false
            }
        ],
        "bJQueryUI": true,
        "sPaginationType": "full_numbers"
    });
}

Table.renderIdColumn = function(oObj, id, lTable) {
    return '<input type="checkbox" value="'  id + '" />';
};

Table.renderNameColumn = function(oObj, name, lTable) {
    var id = oObj.aData[0];
    return '<a href="/obj/edit/' + id + '">' + name + '</a>';
};

所以在创建 Table 对象的时候,我需要拦截对 Table.RenderIdColumn 和 Table.renderNameColumn 的调用,这样我才能断言结果。到目前为止,这是我在 Jasmine 中所拥有的:

describe("Table", function() {
    var lTable;

    // Write a DOM table that will be rendered by the jQuery DataTable plugin
    beforeEach(function() {
        $('<table id="storeTable"></table>').appendTo('body');
        var headerCellClasses = ["idColumn","nameColumn"];
        var headerRow = $('<tr></tr>');
        $.each(headerCellClasses, function(index, value) {
            headerRow.append('<th class="' + value + '"></th>')
        });
        $('<thead></thead>').append(headerRow).appendTo('#lTable');
        $('<tbody></tbody>').appendTo('#lTable');
    });

    afterEach(function() {
        // First remove DataTables enhancements
        lTable.fnDestroy();
        // Now remove from DOM
        $('#lTable').remove();
    });

    describe("when edit links are shown", function() {
        it("should render a checkbox in ID column", function() {
            spyOn(Table, "renderIdColumn");
            lTable = initializeDataTable();
            var oSettings = lTable._table.fnSettings();
            var id = 1;
            var obj = {
                oSettings: oSettings,
                iDataColumn: 0,
                iDataRow: 0,
                mDataProp: 0,
                aData: oSettings.aoData[0]._aData
            }

            var expected = '<input type="checkbox" value="'+ id +'" />';
            expect(Table.renderIdColumn).toHaveBeenCalledWith(obj, id, lTable);
            var results = Table.renderIdColumn(obj, id, lTable);
            expect(results).toEqual(expected);
        });
        it("should render the name column with a proper link", function() {
            spyOn(Table, "renderNameColumn");
            lTable = initializeDataTable();
            var oSettings = lTable._table.fnSettings();
            var name = "Name";
            var obj = {
                oSettings: oSettings,
                iDataColumn: 3,
                iDataRow: 0,
                mDataProp: 3,
                aData: oSettings.aoData[0]._aData
            }

            var expected = '<a href="/obj/edit/1">Name</a>';
            expect(Table.renderNameColumn).toHaveBeenCalledWith(obj, name, lTable);
            var results = Table.renderNameColumn(obj, name, lTable);
            expect(results).toEqual(expected);
        });
    });

});

function initializeDataTable() {
    // Mock the AJAX call to the server from DataTables plugin
    spyOn($.fn.DataTable.defaults, "fnServerData").andCallFake(function( sUrl, aoData, fnCallback, oSettings ) {
        var json = {
            iEcho: 1,
            iTotalRecords: 1,
            iTotalDisplayRecord: 1,
            aaData: [
                [1, "Name"]
            ]
        }
        fnCallback(json);
    });
    return new Table("lTable");
}

在这两个测试用例中,变量“结果”都是“未定义”。我需要测试这些方法以确保它们呈现正确的 HTML,但我似乎无法弄清楚如何断言返回值。一旦我对该方法进行了间谍活动,它似乎不会返回任何内容。我试过插入

Table.renderIdColumn.reset();
Table.renderNameColumn.reset();

但是这些都没有做任何事情......也许是因为我的方法是静态的?仅供参考,这些方法是静态的,因为如果它们是实例方法,我无法正确分配“间谍”。 Table 构造函数调用 DataTables 插件,这将导致这些方法被自动调用,因此我无法构造 Table 对象,然后对这些方法进行监视。

【问题讨论】:

    标签: jquery datatables jasmine


    【解决方案1】:

    当您编写 spyOn(Table, "renderIdColumn") 时,您(实际上)将 Table.renderIdColumn 替换为不返回任何内容的函数。

    如果你想断言它被调用并且仍然返回原来的结果,写spyOn(Table, "renderIdColumn").andCallThrough()

    您提到的.reset() 语法只会重置间谍的内部调用计数 (IIRC)。

    【讨论】:

    • 在哪里检查返回值?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-13
    • 1970-01-01
    相关资源
    最近更新 更多