我正在使用Jasmine对一些JavaScript进行单元测试,并希望监视(模拟)由jQuery选择器访问的DOM元素。
我的规格是:
it("should be able to mock DOM call", function() {
spyOn($("#Something"), 'val').andReturn("bar");
result = $("#Something").val();
expect(result).toEqual("bar");
});
在我的specrunner.html中,我有:
<input type="hidden" id="Something" value="foo" />
不幸的是,规范失败了:
应该能够模拟DOM调用预期'foo'等于'bar'。
答案 0 :(得分:92)
这一行错了:
spyOn($("#Something"), 'val').andReturn("bar");
Jasmine的spyOn函数需要两个参数。第一个是现有对象。第二个是函数名称作为字符串。您正确地将函数名称作为字符串传递(“val”),但您没有将现有对象作为第一个参数传入。
$("#Something")
...不是现有对象。它是jQuery选择器的结果(返回值)。更具体地说,它将返回一个表示匹配节点的jQuery对象 - 有点像结果数组。
$
...是一个现有的对象。
$.fn
...是一个现有的对象。
$("#Something")
... 不现有对象 - 它是 jQuery选择器的结果。
这将有效:
it("should be able to mock DOM call", function () {
//spyOn($.fn, "val").andReturn("bar"); //pre-jasmine 2.0 syntax
spyOn($.fn, "val").and.returnValue("bar"); //Jasmine 2.0 Syntax
var result = $("#Something").val();
expect(result).toEqual("bar");
});
答案 1 :(得分:27)
好像我找到了很好的解决方案
it "should open past statuses", ->
# We can't use $('.past') here cause each time $('.past') called it returns different objects
# so we need to store spy in variable
showSpy = spyOn($.fn, 'show')
# do the stuff
$('.show-past').click()
# then check if 'show' action was called
expect($.fn.show).toHaveBeenCalled()
# and if it realy our object
expect(showSpy.mostRecentCall.object.selector).toEqual('.past')
这不是基于您的代码,但我希望这可以帮助某人。而且,是的,CoffeScript中的例子。
答案 2 :(得分:16)
问题是两次调用$返回两个不同的jQuery包装节点。
这应该有效:
it("should be able to mock DOM call", function(){
// var node = $("Something");
// spyOn(node, 'val').andReturn('bar');
// expect(node.val()).toEqual('bar');
var node = $("Something");
spyOn(node, 'val').and.returnValue('bar');
expect(node.val()).toEqual('bar');
});
下一次,帮助在Jasmine邮件列表中更为普遍:jasmine-js@googlegroups.com。
答案 3 :(得分:3)
您可以创建自己的假DOM元素,然后像往常一样使用$(&#39; #elementid&#39;)[0]
addFakeElementWithId = function (elementId) {
var fake = document.createElement("div");
fake.setAttribute("id", elementId);
document.body.appendChild(fake);
};
答案 4 :(得分:2)
我编写了一个辅助函数,它接受一个id / value-pairs数组。
var jasminTestHelper = {
spyOnValAndFake : function(obj) {
var i, j;
spyOn($.fn, 'val').andCallFake(function() {
for ( i = 0, j = obj.length; i < j; i++) {
if (this.selector === '#' + obj[i][0]) {
return obj[i][1];
}
}
})
}
}
每对告诉faker-function哪个id,如果使用id-selector调用jQuery-val() - 函数,则应返回该值。它的使用方式如下:
jasminTestHelper.spyOnValAndFake([["id1", "value1"], ["id2", "value2"]]);
如果在您的测试函数中调用$('#id1').val()
,则假函数返回value1
,如果调用$('#id2').val()
,则返回value2
。因此,您不需要使用DOM,只需模拟jQuery-val() - 函数并模拟返回值。其他jQuery函数可能会以同样的方式嘲笑。
答案 5 :(得分:1)
我认为我的茉莉花版本(2.0.3)有所改变,因此Alex York的解决方案不能正常工作,但绝对给了我一条路。所以这是工作规范 要测试的jquery代码
"20150804030251".compareTo("20150804040544");
这里是茉莉花规格的一部分
$('someSelector').data('someAttribute').enable();
更精细的规范可以使用另一个模拟级别
var mockJqueryObject = { enable:function(){},disable:function(){}};
//this mocks the .data('someAttribute') in above code.
spyOn($.fn, "data").and.returnValue(mockSelectBoxObject);