javascript - externo - ¿Cómo verifico los eventos jQuery AJAX con Jasmine?
cargar pagina en div javascript (6)
Aquí hay un conjunto de pruebas de ejemplo simple para una aplicación js como esta
var app = {
fire: function(url, sfn, efn) {
$.ajax({
url:url,
success:sfn,
error:efn
});
}
};
un paquete de prueba de muestra, que llamará a devolución de llamada en función de la regexp url
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();
});
});
Intento utilizar a Jasmine para escribir algunas especificaciones BDD para solicitudes jQuery AJAX básicas. Actualmente estoy usando Jasmine en modo independiente (es decir, a través de SpecRunner.html
). Configuré SpecRunner para cargar jquery y otros archivos .js. ¿Alguna idea de por qué lo siguiente no funciona? has_returned no se convierte en realidad, ¡incluso el "yuppi"! alerta se muestra bien.
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);
});
});
¿Cómo pruebo que se ha llamado a la devolución de llamada? Cualquier apunte a blogs / material relacionado con las pruebas async jQuery con Jasmine será muy apreciado.
Cuando especifico el código ajax con Jasmine, resuelvo el problema espiando cualquier función dependiente que inicia la llamada remota (como, por ejemplo, $ .get o $ ajax). Luego recupero las devoluciones de llamada y las pruebo discretamente.
Aquí hay un ejemplo que mencioné recientemente:
Mira el proyecto jazmín-ajax: http://github.com/pivotal/jasmine-ajax .
Es un complemento auxiliar que (para jQuery o Prototype.js) stubs en la capa XHR para que las solicitudes nunca se salgan. Entonces puede esperar todo lo que quiera sobre la solicitud.
Luego le permite proporcionar respuestas de aparatos para todos sus casos y luego escribir pruebas para cada respuesta que desee: éxito, fracaso, no autorizado, etc.
Elimina las llamadas de Ajax del campo de las pruebas asincrónicas y le proporciona mucha flexibilidad para probar cómo deberían funcionar sus controladores de respuesta reales.
Pruebe jqueryspy.com Proporciona una sintaxis elegante similar a jquery para describir sus pruebas y permite que las devoluciones de llamadas se prueben después de que el ajax se haya completado. Es ideal para las pruebas de integración y puede configurar los tiempos máximos de espera de AJAX en segundos o milésimas de segundo.
Siento que necesito proporcionar una respuesta más actualizada ya que Jasmine ahora está en la versión 2.4 y algunas funciones han cambiado desde la versión 2.0.
Por lo tanto, para verificar que se haya llamado a una función de devolución de llamada dentro de su solicitud AJAX, debe crear un espía, agregarle una función callFake y luego usar el espía como su función de devolución de llamada. Así es como funciona:
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
});
});
});
He hecho el truco para la función de éxito, así como la función de error para asegurarme de que Jasmine ejecutará las especificaciones tan pronto como sea posible, incluso si su AJAX devuelve un error.
Si no especifica una función de error y su AJAX devuelve un error, tendrá que esperar 5 segundos (intervalo de tiempo de espera predeterminado) hasta que Jasmine arroje un error Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
. También puede especificar su propio tiempo de espera de esta manera:
it("should get the content of an XML file", function(done)
{
// your code
},
10000); // 10 seconds
Supongo que hay dos tipos de pruebas que puedes hacer:
- Pruebas unitarias que simulan la solicitud AJAX (utilizando los espías de Jasmine), lo que le permite probar todo el código que se ejecuta justo antes de la solicitud AJAX, e inmediatamente después . Incluso puede usar Jasmine para falsificar una respuesta del servidor. Estas pruebas serían más rápidas, y no necesitarían manejar un comportamiento asíncrono, ya que no existe ningún AJAX real.
- Pruebas de integración que realizan solicitudes AJAX reales. Estos deberían ser asincrónicos.
Jasmine puede ayudarte a hacer ambos tipos de pruebas.
Aquí hay una muestra de cómo puede falsificar la solicitud AJAX, y luego escribir una prueba unitaria para verificar que la solicitud falsa de AJAX iba a la URL correcta:
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"
});
}
Para Jasmine 2.0 use en su lugar:
expect($.ajax.calls.mostRecent().args[0]["url"]).toEqual("/products/123");
como se señala en esta respuesta
Aquí hay una prueba unitaria similar que verifica que se realizó su devolución de llamada, cuando una solicitud AJAX se completa con éxito:
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
});
}
Para Jasmine 2.0 use en su lugar:
spyOn($, "ajax").and.callFake(function(options) {
como se señala en esta respuesta
Finalmente, ha insinuado en otro lugar que es posible que desee escribir pruebas de integración que realicen solicitudes AJAX reales, para fines de integración. Esto se puede hacer usando las características asincrónicas de Jasmine: wait (), waitsFor () y runs ():
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
});
}