2012-04-23 68 views
7

完全披露......这是我的第一个SO问题。如果我遗漏任何东西,请客气。 ;-)使用Jasmine测试窥探方法的返回值

我开始使用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.RenderIdColumn和表.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(); 

但是这些都没有做任何事......也许是因为我的方法是静态的?仅供参考,这些方法是静态的,因为如果它们是实例方法,我不能正确分配“间谍”。 Table构造函数调用DataTables插件,这会导致这些方法被自动调用,所以我不能构造Table对象,然后在这些方法上放置间谍。

回答

5

当你编写spyOn(Table, "renderIdColumn")时,你正在(有效)用一个不返回任何东西的函数替代Table.renderIdColumn

如果要断言它被调用并仍然返回原始结果,请编写spyOn(Table, "renderIdColumn").andCallThrough()

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