【问题标题】:How to unit test a jQuery selector?如何对 jQuery 选择器进行单元测试?
【发布时间】:2009-10-30 01:04:11
【问题描述】:

只是一个简单的问题...我目前有以下带有选择器的 jQuery 代码。

var ID = "idControl"
function doesTreeViewExist()
{
    if($('#' + ID).length == 0)
    {
        return false;
    }
    else
    {
        return true;
    }
}

我想知道如何编写测试以使用 QUnit 测试选择器?更具体地说,我在想出语法/代码时遇到了麻烦。

编辑:

好的,假设现在我想模拟选择器调用,因为我无法访问实际网站。我使用 JsTestDriver 作为我的测试工具,这意味着我无法触摸正在运行测试的浏览器(否则测试运行将停止)。在这种情况下怎么办?我怎么可能测试代码?

谢谢。

【问题讨论】:

    标签: javascript jquery unit-testing qunit


    【解决方案1】:

    您发布的功能可以大大简化:

    var ID = "idControl";
    function doesTreeViewExist() {
      return !!$('#' + ID).length;
    }
    

    使用!! 构造(双位非),将length 属性转换为布尔值,仅当长度为零时才会返回false

    谈到 qUnit,您可以轻松地设置一个简单的测试,如下所示:

    test("Your selector test", function() {
      ok($('#idControl').length > 0, "idControl exists");
      // or simply
      ok($('#idControl').length, "idControl exists");
    });
    

    ok 函数执行一个布尔断言,相当于 JUnit 的 assertTrue。

    【讨论】:

      【解决方案2】:

      我手动测试选择器,然后将它们传递给使用它们的代码。然后我可以对使用它们的代码进行单元测试。如果您只想测试一个选择器,您需要访问它所影响的 HTML。您的测试可能包括要定位的 HTML,例如:

      test("selector works", function() {
          var html = $('<input type="select"><option value=0/></input');
      
          var result = $('option', html);
      
          ok(result.count() == 1);
      });
      

      但我不这样做...我将选择器放在代码的边缘,这样我就可以快速找到它们并在调试器下单步执行它们。我将有一个简单的类,其属性就是那些选择器。然后我将模拟/存根那个简单的类,这样我就可以为依赖于这些选择器的所有内容编写代码。 我不测试我的选择器的原因是因为它们所针对的 HTML 是由 ASP.NET 代码生成的,并且很难从 javascript 测试中获得。但我可以将它们包装在一个不起眼的对象(“http://xunitpatterns.com/HumbleObject.html”)中,然后测试依赖于那个不起眼的对象的代码。这是一个简单的包装类,我可以用测试替身代替:

      var createSelectWidget = function(rootSelector)
      {
          return {
              userText : $('span', rootSelector),
              inputList : $('option', rootSelector),
          };
      }
      

      无论你使用什么依赖注入模式,你都可以像下面那样存根它。假设我的小部件有一个选择输入来读取它的值,以及我想将一些结果写入的跨度:

      var createSelectWidgetStub = function()
      {
          return {
              userText : { text = function() {}},
              inputList : { val = function() {}},
          };
      }
      

      然后我可以在我想隔离依赖但不关心与该依赖的交互的测试中传递这个存根。当我想验证与依赖项的交互时,我可以使用 JSMock 模拟它。假设我想验证与输入列表的交互,我会准备一个带有模拟的一个元素的存根:

      var selectMock = createSelectWidgetStub();
      selectMock.inputList = mc.createMock(selectMock.inputList);
      

      【讨论】:

      • &lt;input type="select" /&gt; 无效,您应该使用 &lt;select&gt; 元素,同样在您的第一个示例中 count() 未定义,我认为您想使用 size() 但我会推荐您只需使用 length 属性。
      • 这是个好主意。但这听起来像是一个框架会为我处理它而不是我手动完成的事情。但是如果不允许使用其他框架,这肯定是一种方法。
      • CMS- 是的,我只是假设一些 HTML。这不是问题的重点。
      • BeraCim- 如果你找到一个可以帮助这个的框架,请告诉我。我使用 QUnit 测试框架和 JSMock 库,所以我使用现有的可用工具。
      【解决方案3】:

      我使用 Jack 并成功模拟了 jquery 调用并返回了自定义长度和预期结果。

      类似:

      jack (function() {
          jack.expect("$").exactly("1").withArguments("#" + ID).returnValue( {length:0} );
          doesTreeViewExist()
          assertEquals(false, result);
      });
      

      我还设法提供了一个 DOM 结构来满足 jquery 调用,因为我正在使用 JsTestDriver 的内置函数 HtmlDoc 之一。比如:

      /*:DOC += <span id="idControl"></span> */
      

      或者简单地创建一个没有指定id的DOM结构来获取错误的声明。

      HTH。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-09-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-25
        • 2012-01-08
        • 2019-11-02
        相关资源
        最近更新 更多