2012-02-24 20 views
6

JS ağır web uygulaması için QUnit JavaScript testlerini uygulamaya çalışıyoruz. JQuery AJAX isteklerini içeren yöntemleri başarılı bir şekilde test etmenin bir yolunu bulmaya çalışıyoruz. Biz tercihen yerine gerçek someURL.php bir stubbed URL ile, fire yöntemi test etmek için bir yol bulmaya çalışıyoruzQUnit ile AJAX isteklerini test etme

var X = function() { 
    this.fire = function() { 
     $.ajax("someURL.php", { 
      data: { 
       userId: "james" 
      }, 
      dataType: "json", 
      success: function(data) { 
       //Do stuff 
      } 
     }); 
    }; 
}; 
var myX = new X(); 
myX.fire(); 

: Örneğin, aşağıdaki yapıcı işlevini (Açıkçası bu çok basit bir örneğidir) var.

anda bana sadece bariz çözüm URL eklemek ve success geri arama, yapıcı işlevine argüman olarak. Bu şekilde, testte, X'un yeni bir örneğini oluşturabilir ve saplama URL'sini iletebiliriz ve saplama yanıt verdiğinde çalışacak bir geri arama yapabiliriz. Örneğin, bu çok hoş bir çözüm gibi görünmemektedir. Daha iyi bir yolu var mı? jQuery ile

cevap

9

, bir vaat olarak .ajax() döner, böylece size seçeneklerinde tanımlamak sadece tek success, complete ve error olanlardan daha (aşağıya bakınız) daha işleyicileri ekleyebileceğiniz xhr nesneyi kullanabilirsiniz. Dolayısıyla, eşzamanlama işleviniz xhr nesnesini döndürebilirse, teste özgü işleyicileri ekleyebilirsiniz.

URL'ye gelince, bu biraz daha yanıltıcıdır. Bazen yerel sunucuda çok basit bir Düğüm sunucu kurdum, bu sadece gerçek sunucudan kopyalanmış olan yanıtları servis ediyor. Test paketinizi aynı sunucudan çalıştırırsanız, URL'leriniz üretim sunucusu yerine test sunucusuna isabet edecek mutlak yollar olmalıdır. Ayrıca bir sunucu onları gördükçe taleplerin bir kaydını da alırsınız. Veya kodun nasıl işlediğini görmek istiyorsanız, test sunucusunun hatalara veya amaçlara kötü yanıtlar göndermesini sağlayabilirsiniz.

Ancak bu elbette oldukça karmaşık bir çözümdür. Daha kolay olanı, URL'lerinizi bunları test paketinden yeniden tanımlayabileceğiniz bir yerde tanımlamaktır. Örneğin:

/* in your code */ 
var X = function() { 
    this.fire = function() { 
     return $.ajax({ url: this.constructor.url, ... }); 
    }; 
}; 
X.url = "someURL.php"; // the production url 

/* in your tests */ 
X.url = "stub.php"; // redefine to the test url 

Ayrıca QUnit sizin için stop() çağıran bir asyncTest işlevi vardır. Yeniden ne zaman başlayacağınızı takip etmek için küçük bir yardımcı ekleyin ve oldukça iyi bir çözümün var.

Burada Temelde

// create a function that counts down to `start()` 
function createAsyncCounter(count) { 
    count = count || 1; // count defaults to 1 
    return function() { --count || start(); }; 
} 

// .... 

// an async test that expects 2 assertions 
asyncTest("testing something asynchronous", 2, function() { 
    var countDown = createAsyncCounter(1), // the number of async calls in this test 
     x = new X; 

    // A `done` callback is the same as adding a `success` handler 
    // in the ajax options. It's called after the "real" success handler. 
    // I'm assuming here, that `fire()` returns the xhr object 
    x.fire().done(function(data, status, jqXHR) { 
     ok(data.ok); 
     equal(data.value, "foobar"); 
    }).always(countDown); // call `countDown` regardless of success/error 
}); 

countDown önce ne gelen belirttiğiniz sıfıra sayar ve sonra start() çağıran bir işlev olduğunu yaptık budur. Bu durumda, 1 uyumsuz çağrı var, bu nedenle countDown bundan geri sayılır. Ve ajax çağrısı bittiğinde bunu yapar, nasıl gittiğine bakılmaksızın, bir always geri çağrısı olarak kurulduğundan.
Ve asyncTest 2 iddialarını beklemek anlattı çünkü .done() geri arama asla denir eğer hiçbir iddialar çalıştırılacak olacağından, bu bir hata rapor edeceğiz. Yani eğer çağrı tamamen başarısız olursa, bunu da bilirsiniz. Hata durumunda bir şeyler kaydetmek istiyorsanız, söz zincirine bir .fail() geri bildirimi ekleyebilirsiniz. jQuery spy kullanarak

+0

Bu harika. Çok teşekkürler :) –

2

deneyin. Ajax'i test etmek için jQuery tanıdık sözdizimini kullanmanın daha kolay bir yolunu oluşturdum.

Check this link

3

o (ve) sunucu tarafında ayrı olarak çalıştırılabilir bir birim test ise, sadece ne olursa olsun davranışını simüle etmek $.ajax "yerine" olabilir. Bir kolay örnek: çünkü, değil karmaşık bir cevabı varsa

// Simulate a successfully response 
$.ajax = function(url, opts) { 
    opts.success = function(data) { 
    console.log(data); 
    start(); 
    } 
    _real_ajax('stub.php', opts) 
} 

, ben ilk yaklaşım tercih:

test("Test AJAX function", function() { 
    // keep the real $.ajax 
    var _real_ajax = $.ajax; 

    // Simulate a successful response 
    $.ajax = function(url, opts) { 
    opts.success({expected: 'response'}); 
    } 

    var myX = new X(); 
    // Call your ajax function 
    myX.fire(); 
    // ... and perform your tests 

    // Don't forgot to restore $.ajax! 
    $.ajax = _real_ajax; 
}); 

Açıkçası de stubbed url/verilerle gerçek ajax arama gerçekleştirebilirsiniz daha hızlı ve anlaşılması kolaydır.
Bununla birlikte, başka bir yol alabilir ve Ajax mantığını kendi yöntemine koyabilirsiniz, böylece testler sırasında kolayca koyabilirsiniz.

+0

Testlerimi sunucudan ayırmak için, bu kütüphanede çok başarılı oldum https://github.com/jakerella/jquery-mockjax –