完全披露......这是我的第一个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对象,然后在这些方法上放置间谍。