【问题标题】:How to test jquery and ajax calls using JsTestDriver?如何使用 JsTestDriver 测试 jquery 和 ajax 调用?
【发布时间】:2011-10-06 18:16:39
【问题描述】:

我有一个用 jQuery 构建的动态页面。 Html 片段从mustache 模板加载。这些模板是从一个 url 下载的,我想对整个 html 构造进行单元测试:

JsTestDriver 测试是:

AppTest = TestCase("AppTest")

AppTest.prototype.test = function() {
    var actualHtml = "";

    getHtml({ "title": "title", "header": "header", "text": "text", "authors": [ {"firstname": "firstname", "lastname": "lastname"} ] }, function(html) {
        actualHtml = html;
    });

    assertEquals("expected html", actualHtml);
};

还有代码:

function getHtml(json, resultFunc) {
   jQuery.ajax({
            url: "url/to/mustache/template",
            success: function(view) {
                    resultFunc(mergeArticleModelAndView(json, view));
            },
            error: function(jqXHR, textStatus, errorThrown) {
                    resultFunc(textStatus + " errorThrown: " + errorThrown);
            },
            dataType: 'text',
            async: false 
    });
}

然后我启动测试,结果是:

$ java -jar JsTestDriver-1.3.2.jar --port 9876 --browser /usr/bin/firefox --tests all
F
Total 1 tests (Passed: 0; Fails: 1; Errors: 0) (8,00 ms)
  Firefox 5.0 Linux: Run 1 tests (Passed: 0; Fails: 1; Errors 0) (8,00 ms)
    AppTest.test failed (8,00 ms): AssertError: expected "expected html" but was "error errorThrown: [Exception... \"Component returned failure code: 0x80004005 (NS_ERROR_FAILURE)\"  nsresult: \"0x80004005 (NS_ERROR_FAILURE)\"  location: \"JS frame :: http://localhost:9876/test/main/js/jquery.min.js :: <TOP_LEVEL> :: line 16\"  data: no]"
  ()@http://localhost:9876/test/test/js/app_test.js:25

所以错误回调已经被调用,我不明白为什么它会与 JsTestDriver 中断,并且代码在使用浏览器手动调用应用程序时有效

最后一件事,jsTestDriver.conf:

server: http://localhost:9876

load:
  - test/js/app_test.js
  - main/js/jquery.min.js
  - main/js/jquery.mustache.js
  - main/js/app.js

感谢您的建议。更一般地说,您使用哪些单元测试框架进行 javascript 和 DOM 和 jQuery 的命令行测试?

【问题讨论】:

  • 我使用Jasmine。我不通过命令行执行它们,但有一些插件可以做到这一点。我喜欢 Jasmine 的地方是它可以生成类似散文的测试代码。你可以嵌套你的测试。 jQuery也有一个插件,但没有它我很好。

标签: javascript jquery ajax js-test-driver


【解决方案1】:

有了 sinon.js 就更简单了:

TestCase("AppTest", {
setUp: function() {
    this.server = sinon.fakeServer.create();
},
tearDown: function() {
    this.server.restore();
},

"test article html ok": function () {
    this.server.respondWith("mustache template");
    this.server.respond();
    var actualHtml = "";

    getHtml({ "title": "title", "header": "header", "text": "text", "authors": [ {"firstname": "firstname", "lastname": "lastname"} ] }, function(html) {
        actualHtml = html;
    });

    assertEquals("<expected html>", actualHtml);
}

【讨论】:

    【解决方案2】:

    另一种方法是让 JsTestDriver 为您的模板和一些测试 JSON 数据提供服务。下面的配置允许您将静态 JSON 测试数据(例如 my_data.json)放在 src/test/webapp/json 中,并将 Mustache 模板放在 src/main/webapp/templates 中。如果这太 Maven 不适合您的口味,您可以更改它以匹配您的源布局。

    请注意,JsTestDriver 为资产提供 /test/ 预先添加到 serve 属性中指定的 URI,因此 src/test/webapp/json/my_data.json 实际上是从 http://localhost:9876/test 提供的/src/test/webapp/json/my_data.json.

    server: http://localhost:9876
    
    serve:
    - src/main/webapp/templates/*.html
    - src/test/webapp/json/*.json
    
    load:
    - src/main/webapp/js/*.js
    - src/main/webapp/js/libs/*.js
    
    test:
    - src/test/webapp/js/*.js
    

    然后,在测试用例中,您可以轻松加载模板和 JSON 数据。

        testLoadTemplateAndData : function () {
    
            // Variables
            var onComplete, template, data, expected, actual, templateLoaded, dataLoaded;
            dataLoaded = false;
            templateLoaded = false;
            expected = "<h2>Your expected markup</h2>";
    
            // Completion action
            onComplete = function () {
                if (dataLoaded && templateLoaded) {
    
                    // Render the template and data
                    actual = Mustache.to_html(template, data);
    
                    // Compare with expected
                    assertEquals('Markup should match', expected, actual);
    
                }
            };
    
            // Load data with jQuery
            $.ajax({
                url : '/test/src/test/webapp/json/demo.json', 
                success : 
                    function (result) {
                        data = result;
                        dataLoaded = true;
                },
                error : 
                    function () {
                        fail("Data did not load.");
                },
                complete :
                    function () {
                        onComplete();
                    }
                }
            );
    
            // Load the template with jQuery
            $.get('/test/src/main/webapp/templates/demo.html',
                function(result) {
                    template = result;
                    templateLoaded = true;
                }
            )
            .error(function() { fail("Template did not load."); })
            .complete(function() {
                onComplete();
            });
    
        }
    

    当两个 jQuery 回调完成时,Mustache 应该使用 JSON 数据解析模板并呈现预期的输出。

    【讨论】:

      【解决方案3】:

      是的,可以用 jquery 做同样的事情:

      测试代码(只是测试的设置是一样的):

      TestCase("AppTest", {
          setUp: function() {
              this.xhr = Object.create(fakeXMLHttpRequest);
              this.xhr.send=function () {
                  this.readyState = 4;
              };
              this.xhr.getAllResponseHeaders=stubFn({});
              this.xhr.responseText="<expected data>";
              jQuery.ajaxSettings.isLocal=stubFn(true);
              jQuery.ajaxSettings.xhr=stubFn(this.xhr);
          },
      // same test method
      

      以及生产代码:

      function getHtml(model, resultFunc) {
              $.get("/url/to/template", function(view) {
                      resultFunc(mergeArticleModelAndView(model, view));
              });
      }
      

      这就是我们选择的解决方案。

      【讨论】:

        【解决方案4】:

        我找到了一种方法:模拟 ajax 调用。在http://tddjs.com/ 上,第 12 章中有一个示例,git 存储库在这里:http://tddjs.com/code/12-abstracting-browser-differences-ajax.git

        所以测试代码是:

        TestCase("AppTest", {
            setUp: function() {
                tddjs.isLocal = stubFn(true);
                var ajax = tddjs.ajax;
                this.xhr = Object.create(fakeXMLHttpRequest);
                this.xhr.send=function () {
                    this.readyState = 4;
                    this.onreadystatechange();
                };
                this.xhr.responseText="<expected data>";
                ajax.create = stubFn(this.xhr);
            },
        
        
           "test article html ok": function () {
                var actualHtml = "";
        
                getHtml({ "title": "title", "header": "header", "text": "text", "authors": [ {"firstname": "firstname", "lastname": "lastname"} ] }, function(html) {
                    actualHtml = html;
                });
        
                assertEquals("<expected html>", actualHtml);
           }
        });
        

        以及生产代码:

        function getHtml(model, resultFunc) {
                tddjs.ajax.get("http://url/to/template", {
                        success: function (xhr) {
                                resultFunc(mergeArticleModelAndView(model, xhr.responseText));
                        }
                });
        }
        

        在阅读了 jQuery 代码之后,我认为可以模拟 jQuery ajax 请求。参见jquery 1.5 mock ajax

        【讨论】:

          猜你喜欢
          • 2011-10-27
          • 1970-01-01
          • 1970-01-01
          • 2014-03-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多