Wie überprüfe ich jQuery AJAX-Ereignisse mit Jasmine?

Lesezeit: 7 Minuten

Wie uberprufe ich jQuery AJAX Ereignisse mit Jasmine
mnakos

Ich versuche, Jasmine zu verwenden, um einige BDD-Spezifikationen für grundlegende jQuery-AJAX-Anforderungen zu schreiben. Ich verwende Jasmine derzeit im Standalone-Modus (dh durch SpecRunner.html). Ich habe SpecRunner so konfiguriert, dass es jquery und andere .js-Dateien lädt. Irgendwelche Ideen, warum das Folgende nicht funktioniert? has_returned wird nicht wahr, auch wenn das “yuppi!” Alarm wird gut angezeigt.

describe("A jQuery ajax request should be able to fetch...", function() {

  it("an XML file from the filesystem", function() {
    $.ajax_get_xml_request = { has_returned : false };  
    // initiating the AJAX request
    $.ajax({ type: "GET", url: "addressbook_files/addressbookxml.xml", dataType: "xml",
             success: function(xml) { alert("yuppi!"); $.ajax_get_xml_request.has_returned = true; } }); 
    // waiting for has_returned to become true (timeout: 3s)
    waitsFor(function() { $.ajax_get_xml_request.has_returned; }, "the JQuery AJAX GET to return", 3000);
    // TODO: other tests might check size of XML file, whether it is valid XML
    expect($.ajax_get_xml_request.has_returned).toEqual(true);
  }); 

});

Wie teste ich, ob der Rückruf angerufen wurde? Alle Hinweise auf Blogs/Material zum Testen von asynchronem jQuery mit Jasmine werden sehr geschätzt.

1642540387 934 Wie uberprufe ich jQuery AJAX Ereignisse mit Jasmine
Alex York

Ich denke, es gibt zwei Arten von Tests, die Sie durchführen können:

  1. Komponententests, die die AJAX-Anfrage fälschen (unter Verwendung von Jasmines Spionen), sodass Sie Ihren gesamten ausgeführten Code testen können kurz bevor die AJAX-Anforderung und gleich danach. Sie können Jasmine sogar verwenden, um eine Antwort vom Server vorzutäuschen. Diese Tests wären schneller – und sie müssten kein asynchrones Verhalten behandeln – da kein echtes AJAX stattfindet.
  2. Integrationstests, die echte AJAX-Anfragen ausführen. Diese müssten asynchron sein.

Jasmine kann Ihnen bei beiden Arten von Tests helfen.

Hier ist ein Beispiel dafür, wie Sie die AJAX-Anforderung fälschen und dann einen Einheitentest schreiben können, um zu überprüfen, ob die gefälschte AJAX-Anforderung an die richtige URL ging:

it("should make an AJAX request to the correct URL", function() {
    spyOn($, "ajax");
    getProduct(123);
    expect($.ajax.mostRecentCall.args[0]["url"]).toEqual("/products/123");
});

function getProduct(id) {
    $.ajax({
        type: "GET",
        url: "/products/" + id,
        contentType: "application/json; charset=utf-8",
        dataType: "json"
    });
}

Für Jasmin 2.0 verwenden Sie stattdessen:

expect($.ajax.calls.mostRecent().args[0]["url"]).toEqual("/products/123");

wie in dieser Antwort erwähnt

Hier ist ein ähnlicher Komponententest, der überprüft, ob Ihr Rückruf ausgeführt wurde, nachdem eine AJAX-Anforderung erfolgreich abgeschlossen wurde:

it("should execute the callback function on success", function () {
    spyOn($, "ajax").andCallFake(function(options) {
        options.success();
    });
    var callback = jasmine.createSpy();
    getProduct(123, callback);
    expect(callback).toHaveBeenCalled();
});

function getProduct(id, callback) {
    $.ajax({
        type: "GET",
        url: "/products/" + id,
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: callback
    });
}

Für Jasmin 2.0 verwenden Sie stattdessen:

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

wie in dieser Antwort erwähnt

Schließlich haben Sie an anderer Stelle angedeutet, dass Sie vielleicht Integrationstests schreiben möchten, die echte AJAX-Anforderungen stellen – für Integrationszwecke. Dies kann mit den asynchronen Funktionen von Jasmine erfolgen: waits(), waitsFor() und running():

it("should make a real AJAX request", function () {
    var callback = jasmine.createSpy();
    getProduct(123, callback);
    waitsFor(function() {
        return callback.callCount > 0;
    });
    runs(function() {
        expect(callback).toHaveBeenCalled();
    });
});

function getProduct(id, callback) {
    $.ajax({
        type: "GET",
        url: "data.json",
        contentType: "application/json; charset=utf-8"
        dataType: "json",
        success: callback
    });
}

  • +1 Alex tolle Antwort. Tatsächlich stand ich vor einem ähnlichen Problem, für das ich eine Ajax-Anforderung zum Testen einer Frage mit dem zurückgestellten Objekt geöffnet habe. Könntest du einen Blick darauf werfen? Danke.

    – Lorraine Bernhard

    22. August 2012 um 20:12 Uhr

  • Ich wünschte wirklich, Ihre Antwort wäre Teil der offiziellen Dokumentation für Jasmine. Sehr klare Antwort auf ein Problem, das mich seit einigen Tagen umbringt.

    – Darren Newton

    28. September 2012 um 18:30 Uhr

  • Diese Antwort sollte wirklich als offizielle Antwort auf diese Frage gekennzeichnet werden.

    – Thomas Amar

    20. Juni 13 um 6:44 Uhr

  • Die aktuelle Methode zum Abrufen der neuesten Anrufinformationen ist $.ajax.calls.mostRecent()

    – Camiblanch

    14. August 15 um 20:24 Uhr

  • Wie würden Sie das für einfaches JS-Ajax implementieren?

    – Uhrmacher

    4. November 16 um 12:46 Uhr

Schauen Sie sich das Jasmin-Ajax-Projekt an: http://github.com/pivotal/jasmine-ajax.

Es ist ein Drop-in-Helfer, der (entweder für jQuery oder Prototype.js) auf der XHR-Schicht Stubs ausführt, sodass Anfragen niemals hinausgehen. Sie können dann von der Anfrage alles erwarten, was Sie wollen.

Dann können Sie Fixture-Antworten für alle Ihre Fälle bereitstellen und dann Tests für jede gewünschte Antwort schreiben: Erfolg, Fehler, nicht autorisiert usw.

Es nimmt Ajax-Aufrufe aus dem Bereich asynchroner Tests heraus und bietet Ihnen viel Flexibilität zum Testen, wie Ihre eigentlichen Antworthandler funktionieren sollten.

  • Danke @jasminebdd, das jasmine-ajax-Projekt sieht aus wie der Weg zum Testen meines js-Codes. Aber was, wenn ich mit tatsächlichen Anfragen an den Server testen wollte, zB für Konnektivitäts-/Integrationstests?

    – mnakos

    14. Januar 11 um 12:38 Uhr

  • @mnacos jasmine-ajax ist vor allem für Komponententests nützlich, in denen Sie den Aufruf des Servers ausdrücklich vermeiden möchten. Wenn Sie Integrationstests durchführen, ist dies wahrscheinlich nicht das, was Sie möchten, und sollte als separate Teststrategie konzipiert werden.

    – Sebastian Martin

    13. April 12 um 15:37 Uhr

Hier ist eine einfache Beispiel-Testsuite für eine solche App-JS

var app = {
               fire: function(url, sfn, efn) {
                   $.ajax({
                       url:url,
                       success:sfn,
                       error:efn
                   });
                }
         };

eine Beispiel-Testsuite, die den Callback basierend auf url regexp aufruft

describe("ajax calls returns", function() {
 var successFn, errorFn;
 beforeEach(function () {
    successFn = jasmine.createSpy("successFn");
    errorFn = jasmine.createSpy("errorFn");
    jQuery.ajax = spyOn(jQuery, "ajax").andCallFake(
      function (options) {
          if(/.*success.*/.test(options.url)) {
              options.success();
          } else {
              options.error();
          }
      }
    );
 });

 it("success", function () {
     app.fire("success/url", successFn, errorFn);
     expect(successFn).toHaveBeenCalled();
 });

 it("error response", function () {
     app.fire("error/url", successFn, errorFn);
     expect(errorFn).toHaveBeenCalled();
 });
});

  • Danke Alter. Dieses Beispiel hat mir sehr geholfen! Beachten Sie nur, dass bei Verwendung von Jasmine > 2.0 die Syntax für andCallFake spyOn(jQuery, “ajax”).and.callFake( /* your function */ );

    – João Paulo Motta

    12. März 15 um 0:10 Uhr

  • Ich bin mir nicht sicher, ob dies ein Versionsproblem ist, aber ich habe eine Fehlermeldung erhalten .andCallFake, Gebraucht .and.callFake stattdessen. Danke.

    – OO

    13. Februar 19 um 14:21 Uhr

Wenn ich Ajax-Code mit Jasmine spezifiziere, löse ich das Problem, indem ich die abhängige Funktion ausspioniere, die den Remote-Aufruf initiiert (wie zum Beispiel $.get oder $ajax). Dann rufe ich die darauf gesetzten Callbacks ab und teste sie diskret.

Hier ist ein Beispiel, das ich kürzlich gisted:

https://gist.github.com/946704

Probieren Sie jqueryspy.com aus. Es bietet eine elegante jquery-ähnliche Syntax, um Ihre Tests zu beschreiben, und ermöglicht das Testen von Rückrufen, nachdem das Ajax abgeschlossen ist. Es ist großartig für Integrationstests und Sie können maximale Ajax-Wartezeiten in Sekunden oder Millisekunden konfigurieren.

Wie uberprufe ich jQuery AJAX Ereignisse mit Jasmine
pmrotule

Ich habe das Gefühl, dass ich eine aktuellere Antwort geben muss, da Jasmine jetzt Version 2.4 ist und sich einige Funktionen gegenüber Version 2.0 geändert haben.

Um also zu überprüfen, ob eine Rückruffunktion innerhalb Ihrer AJAX-Anforderung aufgerufen wurde, müssen Sie einen Spion erstellen, eine callFake-Funktion hinzufügen und den Spion dann als Ihre Rückruffunktion verwenden. So geht’s:

describe("when you make a jQuery AJAX request", function()
{
    it("should get the content of an XML file", function(done)
    {
        var success = jasmine.createSpy('success');
        var error = jasmine.createSpy('error');

        success.and.callFake(function(xml_content)
        {
            expect(success).toHaveBeenCalled();

            // you can even do more tests with xml_content which is
            // the data returned by the success function of your AJAX call

            done(); // we're done, Jasmine can run the specs now
        });

        error.and.callFake(function()
        {
            // this will fail since success has not been called
            expect(success).toHaveBeenCalled();

            // If you are happy about the fact that error has been called,
            // don't make it fail by using expect(error).toHaveBeenCalled();

            done(); // we're done
        });

        jQuery.ajax({
            type : "GET",
            url : "addressbook_files/addressbookxml.xml",
            dataType : "xml",
            success : success,
            error : error
        });
    });
});

Ich habe den Trick sowohl für die Erfolgsfunktion als auch für die Fehlerfunktion durchgeführt, um sicherzustellen, dass Jasmine die Spezifikationen so schnell wie möglich ausführt, selbst wenn Ihr AJAX einen Fehler zurückgibt.

Wenn Sie keine Fehlerfunktion angeben und Ihr AJAX einen Fehler zurückgibt, müssen Sie 5 Sekunden (Standardzeitüberschreitungsintervall) warten, bis Jasmine einen Fehler ausgibt Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.. Sie können auch Ihr eigenes Timeout wie folgt angeben:

it("should get the content of an XML file", function(done)
{
    // your code
},
10000); // 10 seconds

.

538710cookie-checkWie überprüfe ich jQuery AJAX-Ereignisse mit Jasmine?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy