2012-05-10 13 views
20

Estoy tratando de escribir algunas pruebas con Jasmine, pero ahora tengo un problema si hay algún código que es asincrónico en beforeEach.¿Cómo probar un método en Jasmine si el código en `beforeEach` es asíncrono?

El código de ejemplo se parece a:

describe("Jasmine", function() { 

    var data ; 

    beforeEach(function(){ 
     console.log('Before each'); 
     getSomeDataFromRemote(function(res){ 
      data = res; 
     }); 
    }); 

    it("test1", function() { 
     expect(data).toBe(something); 
     console.log('Test finished'); 
    }); 

}); 

Se puede ver, en el beforeEach, quiero obtener algunos datos de forma remota, y asignarlo a la data de forma asíncrona.

Pero en el test1, cuando intento para verificar:

expect(data).toBe(something); 

Los datos son undefined, porque getSomeDataFromRemote no ha terminado todavía.

¿Cómo corregirlo?

+0

Sé que Mocha puede hacer una configuración asíncrona, pero estoy menos familiarizado con Jasmine. ¿Ha intentado utilizar las [construcciones de especificación asíncrona] (https://github.com/pivotal/jasmine/wiki/Asynchronous-specs) en su 'beforeEach'? Los documentos solo muestran que se usan dentro de las especificaciones, pero también pueden funcionar en 'beforeEach'. –

Respuesta

23

Al igual que la materia asíncrono dentro de un it se puede utilizar el runs y waitsFor en su beforeeach:

define('Jasmine' , function() { 
    var data ; 

    beforeEach(function(){ 
     runs(function() { 
      getSomeDataFromRemote(function(res){ 
       data = res; 
      }); 
     }); 

     waitsFor(function() { return !!data; } , 'Timed out', 1000); 
    }); 

    it("test1", function() { 
     runs(function() { 
       expect(data).toBe(something); 
     }); 
    }); 
}); 

Aunque voy a suponer que es porque este era el código de prueba creo que probablemente debería tener getSomeDataFromRemote la llamada dentro de su it ya que es en realidad lo que se está probando;)

se pueden ver algunos ejemplos más grandes en algunas pruebas que he escrito para una API asíncrona aquí: https://github.com/aaronpowell/db.js/blob/f8a1c331a20e14e286e3f21ff8cea8c2e3e57be6/tests/public/specs/open-db.js

+2

espera Para y se han suspendido las carreras en Jasmine. Ahora, puedes usar done(). Espero que esto ayude - http://jasmine.github.io/2.0/introduction.html#section-Asynchronous_Support –

3

En este caso, normalmente corto la llamada asíncrona para responder de inmediato.

No estoy seguro si lo has visto o no, pero here es un poco de documentación sobre las pruebas asincrónicas con Jasmine.

+0

Acabo de comprobar su enlace, pero todavía no sé cómo hacerlo en mi caso. – Freewind

+0

Concluye su llamada 'getSomeDataFromRemote' en una función' runs', así como las expectativas. Utiliza 'espera' para proporcionar un tiempo de espera que es suficientemente largo antes de que se ejecute su expectativa. Es incómodamente seguro, y puede causar fallas aleatorias. Es por eso que simplemente resuelvo la llamada para regresar de inmediato. [Sinon.js] (http://sinonjs.org/) también proporciona algo de ayuda en el área de ajax si prefieres algo más alejado del metal. – x1a4

+0

gracias, 'runs' y' waitsFor' es exactamente lo que estoy buscando. Pero como @Slace me dio un ejemplo de trabajo y detalle, tengo que aceptar su respuesta. Lo siento ~ – Freewind

15

Jasmine 2.0

Tenga cuidado porque en el nuevo Jasmine 2.0 esto va a cambiar y que va a ser mocha estilo. Debe utilizar la función done() en beforeEach() y it(). Por ejemplo, imagine que desea probar si existe una página y no está vacía, en un servidor LAMP, usando jQuery $.get. En primer lugar es necesario agregar jQuery para el archivo SpecRunner.html, y en su archivo spec.js:

describe('The "index.php" should', function() { 
    var pageStatus; 
    var contents; 

    beforeEach(function (done) { 
     $.get('views/index.php', function (data, status) { 
      contents = data; 
      pageStatus = status; 
      done(); 
     }).fail(function (object, status) { 
      pageStatus = status; 
      done(); 
     }); 
    }); 

    it('exist', function(done) { 
     expect(status).toBe('success'); 
     done(); 
    }); 

    it('have content', function(done) { 
     expect(contents).not.toBe(''); 
     expect(contents).not.toBe(undefined); 
     done(); 
    }); 
}); 

Como se puede ver, se pasa a la función done() como parámetro para beforeEach() y it(). Cuando ejecuta la prueba, it() no se iniciará hasta que se llame al done() en la función beforeEach(), por lo que no se lanzarán las expectativas hasta que tenga la respuesta del servidor.

la página existe

Si la página existe capturamos el estado y los datos de la respuesta del servidor, y lo llamamos done(). Luego verificamos si el estado es "exitoso" y si los datos no están vacíos o no están definidos.

La página no existe

Si no existe la página capturamos el estado de la respuesta del servidor, y lo llamamos done(). Luego verificamos si el estado no es "satisfactorio" y si los datos están vacíos o indefinidos (esto debe ser porque el archivo no existe).

+0

'done()' también es válido para proyectos como [minijasminenode] (https://github.com/juliemr/minijasminenode) –

+0

que encontré antesTodo no es compatible con el estilo asincrónico.la especificación a continuación se ejecutará antes de que allAll llame al " done " – Kaicui

+2

¿Por qué' '' done''' pasa a las funciones '' 'it''' y se llama? ¿Qué podría salir mal si se omitieran del '' 'it'''? – paulhhowells

Cuestiones relacionadas