Estoy escribiendo una aplicación angular2 y tengo problemas para entender cómo escribir pruebas para código asíncrono usando jasmine. Por alguna razón, no veo muchos ejemplos que parezcan terriblemente aplicables a mi situación.
Actualmente estoy tratando de probar un servicio (no un componente) que tiene una dependencia asíncrona de otro servicio. No estoy 100 % seguro de en qué punto de la prueba es válido comprobar los resultados de la llamada asíncrona. ¿Puede simplemente llamar a expect() dentro del controlador asíncrono para su servicio?
service.foo() .then((data) => { //do I check the results in here? expect(data).toEqual({ a: 1, b: 2 }); expect(mockDep.get).toHaveBeenCalled(); });Aquí está la prueba completa.
import { TestBed, inject } from '@angular/core/testing'; import { MyService } from './my.service.ts'; import { MyDependency } from './dependency.service.ts'; class MockDependency { doSomething(): Promise<any> { throw Error('not implemented'); }; } describe('some tests', () => { beforeEach(() => { TestBed.configureTestingModule({ providers: [ MyService, { provide: MyDependency, useClass: MockDependency } ] }); }); }); it('should do something', inject([MyService, MyDependency], (service: MyService, mockDep: MyDependency) => { spyOn(mockDep, 'doSomething').and.callFake(function () { return Promise.resolve({ a: 1, b: 2 }); }); service.foo() .then((data) => { //do I check the results in here? expect(data).toEqual({ a: 1, b: 2 }); expect(mockDep.get).toHaveBeenCalled(); }); }));Hay dos aspectos relacionados con las pruebas asincrónicas de los que debe preocuparse si desea asegurarse de que sus pruebas sean realmente confiables.
En primer lugar, debe asegurarse de que si un resultado se recupera de forma asíncrona, espere hasta que el resultado esté disponible antes de intentar probarlo.
Por lo tanto, si el resultado asíncrono es una promesa, por ejemplo, puede poner su expect en su controlador de then , tal como lo indicó en su pregunta.
El segundo problema del que debe preocuparse es obligar a su propia prueba a esperar a que se ejecuten sus expectativas antes de dar un resultado positivo (o negativo). Si no se ocupa de esto, puede haber casos en los que su expectativa falle, pero debido a que su prueba no esperó a que se completara su acción asincrónica antes de finalizar, la prueba informa un falso positivo.
Hay varias formas de 'hacer esperar su prueba'.
La forma pura de jazmín es pasar un controlador hecho a su función de TI. Luego, jasmine esperará hasta que se llame a ese controlador antes de considerar que la prueba está completa.
p.ej.
it('tests an async action', (done) => { asyncAction().then(result => { expect(result).toEqual(true); done(); }); });Sin embargo, el marco de prueba de angular agrega otras dos opciones a esto. El primero es más fácil de comprender si se siente cómodo con la programación asíncrona.
it('tests an async action', async(() => { asyncAction().then(result => { expect(result).toEqual(true); }); }));en este caso, básicamente envuelve su controlador de prueba en una función asíncrona. Esta función obligará a la prueba a esperar los resultados asincrónicos (por ejemplo, promesas, observables, etc.) para devolver un resultado, antes de permitir que se complete la prueba.
El segundo método es usar fakeAsync, que le permite ocultar por completo la naturaleza asíncrona de su prueba.
it('tests an async action', fakeAsync(() => { let myResult; asyncAction().then(result => { myResult = result; }); tick(); <--- force all async actions to complete expect(myResult).toEqual(true); })); fakeAsync se conecta a todas las funciones asíncronas y le permite tratarlas como síncronas. Puede usar la función tick () para 'obligar a su prueba a esperar' para que se completen las tareas asíncronas antes de continuar.
(No es exactamente eso, pero conceptualmente, puedes pensarlo de esa manera).
Consulte los documentos de Angular para obtener más información.