我如何对这个JavaScript函数进行单元测试,包括对Ajax调用的嘲讽



正如在这个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
    };
}());

我已经成功地为成功案例编写了一个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");
});

首先,下载并包含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等)。文档可在此处找到。

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

最新更新