我很难理解如何设置允许我测试jQuery调用的对象。我不需要模拟任何异步调用或任何东西,只是基本使用。所以让我列出我想要测试的函数(为简单起见而截断):
listGamesCallback : function(data) {
var gameList = $("#gameList select");
gameList.empty();
$.each(data, function() {
var newOption = $('<option>', {value : this.gameId });
newOption.text(string);
newOption.data("isJoinable", isJoinable);
// Add it to the list
gameList.append(newOption);
});
}
我需要在这里模拟jQuery来对这个方法进行单元测试,但是我无法弄清楚如何在javascript中执行此操作。即使没有jsMockito,我也不知道如何使用jQuery在这种情况下具有的属性创建对象。任何帮助都将不胜感激。
我正在使用jsTestDriver,jsHamcrest,jsMockito和jQuery。但是,创建具有这些属性的$对象的通用方法也很棒。谢谢!
对于那些提出来的人,这是我想出来的,似乎有点工作......但我不明白为什么。
var saved$ = $;
var mockContruct = mockFunction();
var mockedGamelist = mock(jQuery);
var mockedOption = mock(jQuery);
mocked$ = (function() {
var test = function(name) {
var args = jQuery.makeArray(arguments);
return mockContruct.call(test, args);
};
$.extend(test, $);
// This is what confuses me. This worked, but it's wierd
// It allows me to use the regular jQuery functions like
// $.each, while returning mocked objects when selectors are used.
test.prototype.constructor = test;
return test;
})();
$ = mocked$;
when(mockContruct).call(anything(), hasItem(containsString("#gameList")))
.thenReturn(mockedGamelist);
when(mockContruct).call(anything(), hasItems(containsString("<option>"), both(object()).and(hasMember("value"))))
.thenReturn(mockedOption);
headerFunctions.listGamesCallback([ {
gameId : 1,
isWhitesTurn : false,
isGameOver : false,
whiteUserName : "foobar",
blackUserName : "barfoo"
} ]);
JsMockito.verify(mockedGamelist).empty();
JsMockito.verify(mockedGamelist).append(mockedOption);
$ = saved$;
答案 0 :(得分:1)
好的,在这里我想出的是以最小的设置完成工作。这里完全需要.extend,以便正确设置jQuery对象。这允许您模拟构造函数以返回可用于运行测试的模拟jQuery对象。作为间谍,jQuery将在所有情况下按预期工作,除非您希望它执行其他操作。这是:
TestCase("HeaderTest", {
testListGamesCallback : function () {
var saved$ = $;
$ = $.prototype.construct = jQuery.extend(spy(jQuery), jQuery);
var mockGameList = mock(jQuery);
when($)(containsString("#gameList")).thenReturn(mockGameList);
headerFunctions.listGamesCallback([ {
gameId : 1,
isWhitesTurn : false,
isGameOver : false,
whiteUserName : "foobar",
blackUserName : "barfoo"
} ]);
verify(mockGameList).empty();
verify(mockGameList).append(object());
$ = saved$;
}
});
对此解决方案的警告是,除了构造函数之外,模拟其他任何东西都有点棘手。您必须设置要模拟的每个单独的函数,然后对行为进行编程。所以:
$.each = mockFunction();
when($.each)(...matchers...).thenReturn(...);
但它仍然允许测试你需要的东西。
答案 1 :(得分:1)
作为alpian答案的扩展,您可以创建DOM元素而无需将它们添加到页面中。使您的JS函数将相关元素作为参数:
listGamesCallback : function(data, gameListSelectElem) {
var gameList = $(gameListSelectElem);
...
并像这样测试它们:
var fakeSelect = $('<select>'),
data = ...;
listGamesCallback(data, fakeSelect[0]);
equal(fakeSelect.find('option').length, 1, 'must have exactly 1 option');
...
上面的最后一行代码是针对qUnit的。拿你需要的任何东西,重点是你可以传递一个从未添加到页面中的DOM元素,然后使用jQuery调查那个DOM元素,找出它是否被正确操作。
答案 2 :(得分:0)
不确定我是否理解你的意思,但如果你想为你创建'数据',这就是我所知道的方法:
var data = [ { id : 1 , name : 'foo' } , { id : 2, name : 'bar' ]
但是 - 如果你想创建一个选项列表,那么代码需要一些修复: 见http://jsfiddle.net/7MMap/
var data = [ { gameId : 1 , name : 'foo' ,isJoinable:true} , { gameId : 2, name : 'bar' ,isJoinable:false}]
listGamesCallback = function(data) {
var gameList = $("#gameList select")
.empty();
$.each(data, function(i,d) {
var newOption = $('<option>', {value : d.gameId })
.text(d.name)
.data("isJoinable", d.isJoinable);
// Add it to the list
gameList.append(newOption);
})
};
listGamesCallback(data);
答案 3 :(得分:0)
模仿jQuery并不是嘲笑的目的。您应该只是嘲笑对象的协作者。 jQuery为您提供了一些实用程序 - 它不是协作者,因此不应该被嘲笑。
您在这里与之合作的是DOM,或代码与DOM之间的某个中间对象。 data
是一个值对象,可以像Avi建议的那样在测试中创建。
在我的JS测试中,我没有嘲笑DOM,我使用真正的DOM并确保拆除我在测试之间创建的任何东西,这看起来效果很好。