javascript - 使用 Jasmine 测试从 jQuery AJAX 回调调用的函数

标签 javascript jquery ajax jasmine

我有一个函数可以对服务进行 AJAX 调用。我试图期望在失败时调用 displayError 函数。

我有一个接受 url 的函数 ajaxCall。成功后,我将结果传递给 displaySuccess,出现错误时,我将详细信息传递给 displayError。

function ajaxCall(url) {
    $.ajax({
        method: "GET",
        url: url,
        data: "json",
        beforeSend: function (xhr) {
            //Do Stuff
        },
        error: function(xhr, textStatus, errorThrown) { displayError(xhr, textStatus, errorThrow, url)},
        success: function (results) { displaySuccess(result) }
    });
}

function displayError(xhr, textStatus, errorThrow, url) { 
    //Do Stuff// 
}
function displaySuccess(results) { 
    //Do Stuff// 
}

在 Jasmine 中,我成功地验证了 URL。我的问题是测试以确保调用 displayError 和 displaySuccess 函数。

到目前为止,我对这个具体问题有以下看法。

describe('The ajaxCall component', function() {
    it('should call the error function when the ajax call fails', function () {
        var obj = {};
        spyOn(obj, 'displayError');

        spyOn($, "ajax").and.callFake(function (options) {
            options.error();

        });


        ajaxCall('/myResource/get');
        expect(obj.method).toHaveBeenCalled();
    });
}

我对单元测试有点陌生,我进行了搜索,试图找到有帮助的建议,但它们会使单元测试失败。我哪里出错了?

最佳答案

这一切都归结为您如何监视您的对象并编写更可测试的代码。让我们研究一些策略。

策略一

鉴于您当前的代码不在一个对象中,您可以通过简单地直接测试它们的实现来测试这些函数是否被调用。

您无需测试函数是否被调用,而是直接测试它们的实现。

示例

describe("strategy 1", function () {
    var ajaxSpy;

    beforeEach(function () {
        ajaxSpy = spyOn($, 'ajax');

        ajaxCall();
    });

    describe("error callback", function () {
        beforeEach(function() {
            spyOn(window, 'alert');

            var settings = ajaxSpy.calls.mostRecent().args[0];
            settings.error();
        });

        describe("when there is an error", function() {
            it("should alert an error message", function() {
                expect(window.alert).toHaveBeenCalledWith('Error');
            });
        });
    });
});

策略2

虽然上述方法有效,但编写测试可能会很麻烦。理想情况下,您希望分别测试调用和实现。

为此,我们可以监视这些函数。由于它们位于全局命名空间中,您可以通过 window 对象监视它们。

示例

describe("strategy 2", function () {
    var ajaxSpy;

    beforeEach(function () {
        ajaxSpy = spyOn($, 'ajax');

        ajaxCall();
    });

    describe("error callback", function () {
        beforeEach(function() {
            spyOn(window, 'displayError');

            var settings = ajaxSpy.calls.mostRecent().args[0];
            settings.error();
        });

        describe("when there is an error", function() {
            it("should alert an error message", function() {
                expect(window.displayError).toHaveBeenCalled();
            });
        });
    });
});

策略三(推荐)

最终的策略,也是我推荐的,与第二种策略有相似的设置,除了我们将我们的实现封装到一个自定义对象中。

这样做可以通过将功能包装在对象中并避免全局命名空间(即 window)使代码更易于测试。

示例

describe("solution 3", function() {
    var ajaxSpy;

    beforeEach(function() {
        ajaxSpy = spyOn($, 'ajax');

        ajaxService.ajaxCall();
    });

    describe("error callback", function() {
        beforeEach(function() {
            spyOn(ajaxService, 'displayError');

            var settings = ajaxSpy.calls.mostRecent().args[0];
            settings.error();
        });

        it("should alert an error message", function() {
            expect(ajaxService.displayError).toHaveBeenCalled();
        });
    });
});

关于javascript - 使用 Jasmine 测试从 jQuery AJAX 回调调用的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37731995/

相关文章:

javascript - Jquery停止点击事件直到功能完成

javascript - data.items.length 总是给出 10 作为输出

jquery - 500(内部服务器错误)从 JQuery/ajax 到 heroku 服务器的 GET 和请求 POST

javascript - AJAX不会发送POST数据

javascript - jQuery ID 选择和动态数组

javascript - 从条形图中删除 0 值

javascript - 禁用按钮设置 onclick

javascript - 聚合物阵列更新

jquery - 防止按 Enter 时执行 ng-click 操作

javascript - TinyTable 排序器得到一个未定义的