7

完全な開示...これは私の最初のSOの質問です。何も残さなくてもよろしくお願いします。;-)

Jasminを使用して、クライアント側のJavascriptオブジェクトの1つをテストし始めています。このオブジェクトは特に、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への呼び出しをインターセプトする必要があります。これが私がこれまでジャスミンに持っていたものです:

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");
}

どちらのテストケースでも、変数「results」は「undefined」です。これらのメソッドをテストして、正しいHTMLをレンダリングしていることを確認する必要がありますが、戻り値をアサートする方法がわからないようです。メソッドをスパイすると、何も返されないようです。挿入してみました

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

But neither of those did anything...maybe because my methods are static? FYI, those methods are static because I can't properly assign the "spy" if they are instance methods. The Table constructor calls the DataTables plugin which will cause these methods to be called automatically so I can't construct a Table object and then put a spy on those methods.

4

1 に答える 1

5

When you write spyOn(Table, "renderIdColumn"), you are (effectively) replacing Table.renderIdColumn with a function that doesn't return anything.

If you want to assert it was called and still return the results of the original, write spyOn(Table, "renderIdColumn").andCallThrough().

The .reset() syntax you mentioned will only reset the spy's internal call counts (IIRC).

于 2012-04-23T20:06:38.740 に答える