繁体   English   中英

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

[英]Testing a function that is called from an jQuery AJAX callback with 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();
    });
}

我对单元测试还有些陌生,因此我一直在寻找试图帮助他们的建议,但这些建议会使单元测试失败。 我在哪里错呢?

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

策略1

如果您当前的代码不在对象内,则可以通过直接测试它们的实现来测试这些函数是否被调用。

您无需直接测试函数的调用,而可以直接测试其实现。

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

策略3(推荐)

最终策略以及我建议的策略与第二种策略具有相似的设置,只是将实现封装到一个自定义对象中。

这样做可以通过在对象中包装功能来使代码更易于测试,并且避免使用全局命名空间(即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();
        });
    });
});

暂无
暂无

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

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