7

正如在这个jsFiddle中看到的,我有一个函数'init',它配置一个按钮,以便在单击它时打开一个进度对话框并发出一个 Ajax 调用。我想对此 JavaScript 代码进行单元测试(使用QUnit),并检查以下情况:

  1. Ajax 调用成功
  2. Ajax 调用失败

我至少需要模拟 Ajax 调用和对 的调用window.open,以及我确定的其他调用,具体取决于单元测试实现。

如何为测试这两种场景的代码编写 QUnit 单元测试?

编辑:需要测试的代码:

var statusmod = (function() {
    var spinner = $("#spinner");

    var init = function(id) {
        var progressDialog = $("#progressdialog-content").dialog({
            autoOpen: false,
            title: "Launching Status Page"
        });
        var errorDialog = $("#errordialog-content").dialog({
            autoOpen: false,
            modal: true,
            buttons: {
                "OK": function() {
                    $(this).dialog("close");
                }
            }
        });

        var btn = $("#button-status");
        btn.button().click(function() {
            spinner.show();

            progressDialog.dialog("open");

            var url = $.validator.format("/api/binid/?id={0}", id);
            // Call Web service to get binary ID
            $.ajax({
                url: url,
                dataType: "json"
            }).done(function(data) {
                window.open($.validator.format("http://status/?Page=Status&Id={0}", data.Id), target = "_newtab");
            }).fail(function(jqXHR, msg, errorThrown) {
                errorDialog.dialog("open");
            }).always(function() {
                progressDialog.dialog("close");
            });

            return false;
        });
    };

    return {
        init: init,
        _spinner: spinner
    };
}());
4

2 回答 2

1

我已经成功地为成功案例编写了一个 QUnit 测试,为失败案例编写了另一个测试,正如您从这个 jsFiddle中看到的那样。我使用Mockjax来伪造 Ajax 响应并模拟成功/失败条件。值得注意的是,我将 Ajax 调用配置为同步的,这样我就可以编写同步测试,因为在异步 Ajax 回调触发后我无法弄清楚如何运行我的测试。

我还利用Sinon.JS库来伪造依赖项并验证对话框是否正确启动。

工作测试代码包含在下面,请参阅我对被测函数的问题(statusmod.init)。如果您认为我遗漏了什么,请告诉我。

var dialogSpy = null;
var windowSpy = null;
var id = "srcId";
var binId = "binId";
var url = $.validator.format("/api/binid/?id={0}", id);
var btnId = "#button-status";

module("Open status page", {
    setup: function() {
        // Allow us to run tests synchronously
        $.ajaxSetup({
            async: false
        });
        windowSpy = sinon.spy(window, "open");
        dialogSpy = sinon.spy();
        sinon.stub($.fn, "dialog", function() {
            return {
                "dialog": dialogSpy
            };
        });

        statusmod.init(id);
    },
    teardown: function() {
        windowSpy.restore();
        $.fn.dialog.restore();
        $.mockjaxClear();
        // Remove click event handler for each test
        $(btnId).unbind();
    }
});

test("Successfully open status page", function() {
    expect(4);

    $.mockjax({
        url: url,
        contentType: "text/json",
        responseText: {
            Id: binId
        }
    });

    var spinner = statusmod._spinner;
    var spinnerSpy = sinon.spy(spinner, "show");

    $(btnId).click();

    ok(spinnerSpy.calledOnce, "Spinner shown");
    ok(dialogSpy.withArgs("open").calledOnce, "Dialog opened");
    ok(dialogSpy.withArgs("close").calledOnce, "Dialog closed");
    equal(windowSpy.lastCall.args[0], $.validator.format("http://status/?Page=Status&Id={0}", binId), "Window opened");
});

test("Binary ID not found on server", function() {
    expect(3);

    $.mockjax({
        url: url,
        contentType: "text/json",
        status: 404
    });

    $(btnId).click();

    ok(dialogSpy.withArgs("open").calledTwice, "Dialogs opened");
    ok(dialogSpy.withArgs("close").calledOnce, "Progress dialog closed");
    ok(!windowSpy.called, "Window not launched");
});
于 2012-08-27T07:50:23.240 回答
0

首先,下载并包含Mockjax

然后模拟你的 ajax 调用:

module("Mock Ajax", {
  setup: function () {
    /** this mocks the ajax call **/
    $.mockjax({
      url: 'yourUrl.php',
      data: {'action': 'your',
        'data': {
          'that': 'you',
          'send': 'here'
        }
      },
      responseText:'{"your": ["returned":"json"],"string"}'
    });
  });
});

然后您可以在测试用例中进行 ajax 调用:

test( "Your testcase", function() {
  $.ajax('yourUrl.php',
    data: {'action': 'your',
       'data': {
      'that': 'you',
      'send': 'here'
    }
  }, function(data) {
      ok("do something with your data");
  });
});

等等,你已经成功地测试了一些东西!您可以在 mockjax 调用中添加额外的参数(isTImeout、isError 等)。文档可以在这里找到。

这些是基础知识,您可以使用非常完整的文档对其进行编辑以满足您的需求。

于 2012-08-23T17:08:00.670 回答