在Jasmine中监视JQuery选择器

Dan*_*ott 60 jquery unit-testing jasmine

我正在使用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");

});
Run Code Online (Sandbox Code Playgroud)

在我的specrunner.html中,我有:

<input type="hidden" id="Something" value="foo" />
Run Code Online (Sandbox Code Playgroud)

不幸的是,规范失败了:

应该能够模拟DOM调用预期'foo'等于'bar'.

Ale*_*ork 93

这条线错了:

spyOn($("#Something"), 'val').andReturn("bar");
Run Code Online (Sandbox Code Playgroud)

Jasmine的spyOn函数需要两个参数.第一个是现有对象.第二个是函数名称作为字符串.您正确地将函数名称作为字符串("val")传递,但您没有将现有对象作为第一个参数传入.

$("#Something")
Run Code Online (Sandbox Code Playgroud)

...不是现有对象.它是jQuery选择器的结果(返回值).更具体地说,它将返回一个表示匹配节点的jQuery对象 - 有点像结果数组.

$
Run Code Online (Sandbox Code Playgroud)

...是现有对象.

$.fn
Run Code Online (Sandbox Code Playgroud)

...是现有对象.

$("#Something")
Run Code Online (Sandbox Code Playgroud)

... 不是现有对象 - 它是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");
});
Run Code Online (Sandbox Code Playgroud)

  • @NathanLong问题在于,每次执行jquery选择器时,都会得到一个全新的对象,因此您设置为侦察的对象将与您在被测代码中获得的对象不同.因此Alex告诉你要监视所有jquery对象的原型($ .fn). (14认同)
  • 我同样感到困惑.`var $ foo = $('#foo')`.现在`$ foo`是一个现有的对象:它是一个jQuery对象.它有一个`val()`方法; 它只是通过将其原型链查找到`jQuery.fn`来实现它.那么为什么我不能做'spyOn($ foo,"val")`?为什么Jasmine的间谍要求我指定方法的定义?我的用例是我要检查,比如说,`hide()`已被调用,不仅仅是一般,而是**$ foo**.所以`spyOn(jQuery.fn,"hide")`并没有给我我想要的信息,但是`spyOn($ foo,"hide")`会 - 如果有效的话. (4认同)

hob*_*lin 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')
Run Code Online (Sandbox Code Playgroud)

这不是基于您的代码,但我希望这可以帮助某人.而且,是的,CoffeScript中的例子.

  • .selector在jQuery 1.7+中已弃用.什么是1.7+版本的替代品? (3认同)

小智 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');
});
Run Code Online (Sandbox Code Playgroud)

下一次,帮助在Jasmine邮件列表中更为普遍:jasmine-js@googlegroups.com.

  • 这是你的答案,jQuery为每个查询返回一个不同的对象,即使它是相同的选择器.您需要引用同一个对象才能正确窥探它.否则,你正在监视一个,并在另一个上执行. (6认同)