使用qunit和mockjax测试ajax调用

时间:2015-01-08 15:33:44

标签: knockout.js qunit mockjax

我正在尝试测试ajax调用。我需要测试正确的URL,并使用正确的数据和结果进行测试。从这个测试失败开始。我得到的错误是“预期:已保存,实际:”。

我的knockout viewmodel中的函数 -

self.functions.save = function () {
    $.ajax({
        url: '/x',
        data: { test: "" },
        dataType: "json",
        success: function (response) {
            self.saved(response.message);
        }
    });
};

Qunit测试 -

test('save does ajax call', function () {
        $.mockjax({
            url: '/x',
            dataType: 'json',
            responseText:
                {
                    message: 'saved'
                }
        });
        mock.functions.save();
        equal(mock.saved(), "saved");
});

1 个答案:

答案 0 :(得分:2)

这里的问题是执行的顺序。您的save()方法执行异步操作,Mockjax尊重它。因此,当您在测试中调用mock.functions.save();时,该函数会立即返回,这意味着您的equal()断言在源代码中的ajax调用的success处理程序之前触发码。您需要为测试添加一些方法以了解Ajax调用何时完成。在下面的示例中,我使用了一个简单的回调函数,但您也可以使用Promises或其他方法执行此操作。

源代码:

self.functions.save = function (callback) {
    callback = callback || function(){};  // ensure we have a callback
    $.ajax({
        url: '/x',
        data: { test: "" },
        dataType: "json",
        success: function (response) {
            self.saved(response.message);
        },
        // when the call is finished, execute the callback (success or error)
        complete: function () {
            callback();
        }
    });
};

在测试中,您需要使用QUnit的异步功能。有new way to do async testing in v1.16.0,所以要么更新,要么您可以查找the old way

QUnit.test('save does ajax call', function (assert) {
    // first tell QUnit you need to perform async actions...
    var done = QUnit.async();

    $.mockjax({
        url: '/x',
        dataType: 'json',
        responseText:
            {
                message: 'saved'
            }
    });
    mock.functions.save(function() {
        // this callback fires when the async action is complete,
        // so now we do our assertions
        assert.equal(mock.saved(), "saved");

        // ...and now we tell QUnit we're done with async actions
        done();
    });
});