简体   繁体   English

如何使用 JsTestDriver 测试 jquery 和 ajax 调用?

[英]How to test jquery and ajax calls using JsTestDriver?

I have a dynamic page built with jQuery.我有一个用 jQuery 构建的动态页面。 Html pieces are loaded from mustache templates. Html 件从小胡子模板加载。 These templates are downloaded from a url, and I would like to unit test the overall html construction:这些模板是从 url 下载的,我想对整个 html 结构进行单元测试:

The JsTestDriver test is: 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);
};

And the code:和代码:

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 
    });
}

Then I launch the tests and the result is:然后我启动测试,结果是:

$ 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

So the error callback has been called, and I don't understand why it breaks with JsTestDriver, and the code works when calling the application manually with a browser所以错误回调已被调用,我不明白为什么它会与 JsTestDriver 中断,并且代码在使用浏览器手动调用应用程序时有效

Last thing, the jsTestDriver.conf:最后一件事,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

Thank you for your advices.谢谢你的建议。 More generally, what unit test frameworks do you use for javascript and command line testing with DOM and jQuery?更一般地说,您使用哪些单元测试框架进行 javascript 以及使用 DOM 和 jQuery 的命令行测试?

An alternative would be to get JsTestDriver to serve your template and some test JSON data.另一种方法是让 JsTestDriver 为您的模板和一些测试 JSON 数据提供服务。 The configuration below allows you to put static JSON test data (eg my_data.json) in src/test/webapp/json and Mustache templates in src/main/webapp/templates.下面的配置允许您将 static JSON 测试数据(例如 my_data.json)放在 src/test/webapp/json 中,并将 Mustache 模板放在 src/main/webapp/templates 中。 You can change this around to match your source layout if this is too Maven-y for your tastes.如果这太 Maven 不适合您的口味,您可以更改它以匹配您的源布局。

Note that JsTestDriver serves the assets with /test/ pre-pended to the URI specified in the serve attribute, so src/test/webapp/json/my_data.json is actually served from http:/ /localhost:9876/test/src/test/webapp/json/my_data.json.请注意,JsTestDriver 使用 /test/ 预置在 serve 属性中指定的 URI 来提供资产,因此 src/test/webapp/json/my_data.json 实际上是从 http:/ /localhost:9876/test/src/ 提供的测试/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

Then, in a test case you can easily load a template and JSON data.然后,在测试用例中,您可以轻松加载模板和 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();
        });

    }

When both jQuery callbacks complete, Mustache should parse the template with the JSON data and render the expected output.当 jQuery 回调完成时,Mustache 应该使用 JSON 数据解析模板并呈现预期的 output。

I found a way to do it: is to mock ajax calls.我找到了一种方法:模拟 ajax 调用。 On http://tddjs.com/ there is an example to do so in chapter 12, and the git repository is here: http://tddjs.com/code/12-abstracting-browser-differences-ajax.git On http://tddjs.com/ there is an example to do so in chapter 12, and the git repository is here: http://tddjs.com/code/12-abstracting-browser-differences-ajax.git

So the test code is:所以测试代码是:

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);
   }
});

And the production code:和生产代码:

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

After having read jQuery code, I think it is possible to mock jQuery ajax request.阅读 jQuery 代码后,我认为可以模拟 jQuery ajax 请求。 Cf also jquery 1.5 mock ajax参见 jquery 1.5 模拟 ajax

Yes it is possible to do quite the same with jquery:是的,可以用 jquery 做同样的事情:

Test code (just the setup the test is the same):测试代码(只是测试的设置是一样的):

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

And the production code:和生产代码:

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

That's the solution that we have chosen.这就是我们选择的解决方案。

With sinon.js it is even simpler:使用 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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM