在 Jasmine 中监视 JQuery 选择器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5337481/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spying on JQuery Selectors in Jasmine
提问by Daniel Elliott
I am unit testing some JavaScript with Jasmine and wish to spy on (mock) an element of the DOM that is accessed by a jQuery selector.
我正在使用 Jasmine 对一些 JavaScript 进行单元测试,并希望监视(模拟)由 jQuery 选择器访问的 DOM 元素。
My spec is:
我的规格是:
it("should be able to mock DOM call", function() {
spyOn($("#Something"), 'val').andReturn("bar");
result = $("#Something").val();
expect(result).toEqual("bar");
});
In my specrunner.html I have:
在我的 specrunner.html 中,我有:
<input type="hidden" id="Something" value="foo" />
Unfortunately the spec fails with:
不幸的是,规范失败了:
should be able to mock DOM call Expected 'foo' to equal 'bar'.
应该能够模拟 DOM 调用预期的 'foo' 等于 'bar'。
回答by Alex York
This line is wrong:
这一行是错误的:
spyOn($("#Something"), 'val').andReturn("bar");
Jasmine's spyOn function expects two parameters. The first is an existing object. The second is a function name as a string. You are correctly passing in the function name as a string ("val") but you are not passing in an existing object as the first parameter.
Jasmine 的 spyOn 函数需要两个参数。第一个是现有对象。第二个是作为字符串的函数名称。您正确地将函数名称作为字符串(“val”)传递,但没有将现有对象作为第一个参数传递。
$("#Something")
...is not an existing object. It is the result (the return value) of a jQuery selector. More specifically, it will return a jQuery object representing the matched nodes - kind of like an array of results.
...不是现有对象。它是 jQuery 选择器的结果(返回值)。更具体地说,它将返回一个表示匹配节点的 jQuery 对象——有点像结果数组。
$
...is an existing object.
...是一个现有的对象。
$.fn
...is an existing object.
...是一个现有的对象。
$("#Something")
...is notan existing object - it is the result of a jQuery selector.
...不是现有对象 - 它是jQuery 选择器的结果。
This will work:
这将起作用:
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");
});
回答by hoblin
Seems like I found good solution
好像我找到了很好的解决方案
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')
This is not based on your code but i hope this can help someone. And, yes, example in CoffeScript.
这不是基于您的代码,但我希望这可以帮助某人。而且,是的,CoffeScript 中的示例。
回答by user588542
The problem is that the two calls to $ return two different jQuery-wrapped nodes.
问题是对 $ 的两次调用返回了两个不同的 jQuery 包装节点。
This should work:
这应该有效:
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');
});
Next time, help is more prevalent on the Jasmine mailing list: [email protected].
下一次,Jasmine 邮件列表上的帮助会更加普遍:[email protected]。
回答by kernowcode
You could create your own fake DOM element and then use $('#elementid')[0] as usual
您可以创建自己的假 DOM 元素,然后像往常一样使用 $('#elementid')[0]
addFakeElementWithId = function (elementId) {
var fake = document.createElement("div");
fake.setAttribute("id", elementId);
document.body.appendChild(fake);
};
回答by Roland Würth
I wrote a helper-function, which accepts an array of id/value-pairs.
我写了一个辅助函数,它接受一组 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];
}
}
})
}
}
Each pair tells the faker-function for which id, which value should be returned if the jQuery-val()-function is called with the id-selector. It is used like this:
如果使用 id-selector 调用 jQuery-val()-function,每一对告诉 faker-function 哪个 id,应该返回哪个值。它是这样使用的:
jasminTestHelper.spyOnValAndFake([["id1", "value1"], ["id2", "value2"]]);
If $('#id1').val()
is called in your function under test, the fake-function returns value1
, if $('#id2').val()
is called it returns value2
. So you don't need to fiddle with the DOM, you just mock the jQuery-val()-function and simulate return-values. Other jQuery-functions could probably mocked the same way.
如果$('#id1').val()
在您的被测函数中被调用,则假函数返回value1
,如果$('#id2').val()
被调用则返回value2
。所以你不需要摆弄 DOM,你只需模拟 jQuery-val() 函数并模拟返回值。其他 jQuery 函数可能会以同样的方式模拟。
回答by Sanjay Bharwani
I think there is a change in my jasmine version (2.0.3), hence the solution by Alex York didn't work as is, but definitely gave me a path. So here is the working spec jquery code which is to be tested
我认为我的 jasmine 版本(2.0.3)有变化,因此 Alex York 的解决方案没有按原样工作,但绝对给了我一条路。所以这是要测试的工作规范 jquery 代码
$('someSelector').data('someAttribute').enable();
here is the jasmine spec part of it
这是茉莉花规格的一部分
var mockJqueryObject = { enable:function(){},disable:function(){}};
//this mocks the .data('someAttribute') in above code.
spyOn($.fn, "data").and.returnValue(mockSelectBoxObject);
A more granular spec could use another level of mock as
更细粒度的规范可以使用另一个级别的模拟作为
spyOn(mockJqueryObject,"enable")
spyOn(mockJqueryObject,"disable")