Testeando AJAX en jQuery

05 Feb 2011

Hace poco tratábamos las Pruebas Unitarias en Javascript utilizando QUnit para la realización de los tests. En esta ocasión, vamos a prestar una atención especial a las pruebas sobre las peticiones AJAX en jQuery utilizando otra de las fantásticas librerías que tenemos disponibles: jquery.mockjax.

jquery.mockjax es un plugin jQuery desarrollado por Jonathan Sharp cuya finalidad es ofrecer una herramienta para realizar pruebas sobre peticiones AJAX con el menor impacto posible sobre el código original. Para ello, emula el comportamiento del servidor interceptando las peticiones y devolviendo aquellos datos que hayamos previamente definido.

Soporta todas las versiones posteriores a la 1.3.2 de jQuery y ha sido probado en los principales navegadores incluyendo Internet Explorer +6, Firefox +3.3, Safari +3, Chrome +3 y Opera +9.

Integrando Mockjax en nuestra aplicación

Para comenzar a utilizar esta herramienta sólo tenemos que descargar el archivo correspondiente desde la página oficial y añadirlo a nuestro código. Si nos resulta más cómodo, podemos utilizar directamente la últiva versión del plugin desde el CDN de github.

<script src="http://github.com/appendto/jquery-mockjax/raw/master/jquery.mockjax.js"></script>

Esto es todo; no necesitamos incluir ningún otro archivo o modificar el DOM para comenzar a utilizar nuestro plugin. Estamos listos para comenzar a testear nuestras peticiones AJAX.

Primeras pruebas

Por lo general, una petición AJAX en jQuery tiene la siguiente estructura:

$.ajax({
  type : "GET",
  url : "/foo/bar.html",
  data : {
      id : 1,
      name : 'Carlos Benitez',
      pass : '1234567890'
  },
  success : function( data ){
    console.log( "First Method Data Saved: " , data );
  }
});

También podemos escribir el código anterior utilizando el shortcut $.get() con el que se identifican más muchos desarrolladores:

$.get( '/foo/bar.html', {
  id : '1',
  name : 'Carlos Benitez',
  pass : '1234567890'
}, function( data ){
  console.log( "Data Saved: " + data );
} );

Llegados a este punto, si quisiéramos ejecutar el código, necesitariamos contar con que la arquitectura REST implementada. Aquí es donde comienza ser interesante el contar con un plugin como Mockjax que emule la respuesta de un servidor interceptando las peticiones realizadas.

Su inicialización más simple, sería la siguiente:

$.mockjax({
  url : '/foo/bar.html',
  responseText : 'Server Response Emulated'
});

Una vez iniciado, el plugin localizará todos los métodos AJAX jQuery ($.ajax, $.get, $.post, etc…) para comprobar la URL a la que realizan la petición con aquellas definidas en el mock. En caso de coincidir, el plugin intercepta la petición y ejecuta su contenido antes de devolver el control al manejador nativo  jQuery.ajax. Si no coinciden las URLs, la petición se devuelve a $.ajax para su ejecución normal.

Definiendo las URLs

Existen varias formas de asignar la URL que nuestro mock debe interceptar. Desde una simple cadena:

$.mockjax({
  url: '/url/to/rest-service'
});

a expresiones regulares que definan rangos:

$.mockjax({
  // Matches /data/quote, /data/tweet but not /data/quotes
  url: /^\/data\/(quote|tweet)$/i
});

Podemos incluso asignar comodines para una mayor cobertura:

$.mockjax({
  // Matches /data/quote, /data/tweet etc.
  url: '/data/*'
});
 
$.mockjax({
  // Matches everything!
  url: '*'
});

Definiendo la respuesta

El segundo aspecto importante es definir la respuesta que esperamos del servidor. Ésta puede ser tanto una cadena (responseText) como una estructura XML (responseXML).

Un ejemplo de respuesta en texto plano podría ser:

$.mockjax({
  url: '/restful/api',
  responseText: 'A text response from the server'
});

Otro ejemplo de respuesta con un formato XML simple sería:

$.mockjax({
  url: '/restful/api',
  // Need to include the xmlDOM plugin to have this translated into a DOM
  responseXML: 'Hello world!'
});

Sin embargo, si necesitamos devolver una gran cantidad de datos, esta solución de texto inline, no resulta muy manejable. Para esos casos, contamos con la posibilidad de cargar los datos directamente con un proxy:

$.mockjax({
  url: '/restful/api',
  proxy: '/mocks/data.json'
});

El otro escenario común es cuando precisamos de un callback donde tengamos acceso a los posibles argumentos utilizados en la petición. Volviendo al ejemplo del principio, tendríamos:

$.mockjax({
  url: '/foo/bar.html',
  response : function( settings ){
    var data = settings.data;
    this.responseText = data;
  }
});
 
$.get( '/foo/bar.html', {
  id : '1',
  name : 'Carlos Benitez',
  pass : '1234567890'
}, function( data ){
  console.log( "Data Saved: " + data );
} );

En esta ocasión, la respuesta de nuestro mock corresponderá a todos los argumentos enviados:

// Data Saved: Object { id=1, name="Carlos Benitez", pass="1234567890"}

Si observamos con atención el ejemplo anterior, hemos utilizado la variable settings para extraer los argumentos. Esta variable contiene además, todos los datos relativos al mock:

  • data. Los argumentos.
  • type. El tipo de petición (GET, POST).
  • url. La URL monitorizada.
  • success. Función para el evento success.

Técnicas avanzadas

Llegados a este punto, ya sabemos cómo simular una respuesta simple de nuestro plugin frente a una petición. Pero, además de texto, podemos emular otros aspectos como la latencia, el estado HTTP, añadir cabeceras adicionales o forzar un timeout.

Para ello, podemos modificar en consecuencia cada uno de nuestros mocks, o sobreescribir el objeto $mockjaxSettings afectando a todas las instancias.

Las opciones por defecto son las siguientes:

$.mockjaxSettings = {
  status:        200,
  responseTime:  500,
  isTimeout:     false,
  contentType:   'text/plain',
  response:      '',
  responseText:  '',
  responseXML:   '',
  proxy:         '',
  lastModified:  null,
  etag:          ''
};

Para modificar una opción en particular, podemos invocarla directamente mediante su correspondiente notación:

$.mockjaxSettings.contentType = 'text/json';

Si sólo precisamos de cambiar un parámetro dentro de un mock particular, lo especificamos en su declaración:

$.mockjax({
  url: '/foo/bar.html',
  responseTime : 200,
  etag : 'xyz123'
});

En el ejemplo anterior, hemos simulado una latencia de 200 milisegundos en la respuesta, una opción interesante para emular grandes transacciones de datos o una alta tasa de tráfico en el servidor objetivo.

Eliminando las instancias Mockjax

Para eliminar todos los controladores Mockjax, sólo tenemos que incluir en nuestro código:

$.mockjaxClear();

Si lo que pretendemos es eliminar un controlador concreto, tendremos que asignar dicho controlador a una variable y después liberarla:

var myMock = $.mockjax({
  // ...
});
$.mockjaxClear( myMock);

Conclusión

Mockjax es un excelente plugin de jQuery para complementar nuestros frameworks de tests cuya finalidad es interceptar las peticiones AJAX devolviendo respuestas predefinidas. Esto evita la necesidad de contar con una infraestructura REST ya funcionando y nos permite aplicar una metodología TDD donde las pruebas se anticipan a la implementación del código.

Más:
Esta entrada fue publicada en Sin categoría. Guarda el enlace permanente.

{2} Comentarios.

  1. fcodiaz

    Muy buena herramientas para cuando no tenemos acceso a los recursos del servidor y no podemos influir en las respuestas del server….

  2. brevetes

    Por post como estos es que me encanta jquery!!
    Gracias.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *