example - ¿Cómo resolver las promesas en AngularJS, Jasmine 2.0 cuando no hay $ scope para forzar un resumen?
promise angular 2 (4)
Parece que las promesas no se resuelven en las pruebas Angular / Jazmín a menos que fuerce un $scope.$digest()
. Esto es tonto IMO pero está bien, tengo que trabajar donde corresponda (controladores).
La situación en la que me encuentro ahora es que tengo un servicio que no se preocupa por ningún ámbito en la aplicación, todo lo que hace es devolver algunos datos del servidor, pero la promesa no parece resolverse.
app.service(''myService'', function($q) {
return {
getSomething: function() {
var deferred = $q.defer();
deferred.resolve(''test'');
return deferred.promise;
}
}
});
describe(''Method: getSomething'', function() {
// In this case the expect()s are never executed
it(''should get something'', function(done) {
var promise = myService.getSomething();
promise.then(function(resp) {
expect(resp).toBe(''test'');
expect(1).toEqual(2);
});
done();
});
// This throws an error because done() is never called.
// Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
it(''should get something'', function(done) {
var promise = myService.getSomething();
promise.then(function(resp) {
expect(resp).toBe(''test'');
expect(1).toEqual(2);
done();
});
});
});
¿Cuál es la forma correcta de probar esta funcionalidad?
Editar: solución de referencia. Aparentemente se ve obligado a inyectar y digerir $ rootScope incluso si el servicio no lo está utilizando.
it(''should get something'', function($rootScope, done) {
var promise = myService.getSomething();
promise.then(function(resp) {
expect(resp).toBe(''test'');
});
$rootScope.$digest();
done();
});
Así que he estado luchando con esto toda la tarde. Después de leer esta publicación, yo también sentí que había algo con la respuesta, resulta que sí. Ninguna de las respuestas anteriores brinda una explicación clara sobre dónde y por qué usar $rootScope.$digest
. Entonces, aquí es lo que se me ocurrió.
Primero, ¿por qué? Necesita usar $rootScope.$digest
cada vez que responda desde un evento no angular o devolución de llamada. Esto incluiría eventos DOM puros, eventos jQuery y otras bibliotecas Promesa de terceros que no sean $q
que es parte de angular.
En segundo lugar, ¿dónde? En tu código, NO tu prueba. No es necesario inyectar $rootScope
en su prueba, solo es necesario en su servicio angular real. Ahí es donde todo lo anterior no deja en claro cuál es la respuesta, muestran $rootScope.$digest
como llamado desde la prueba.
Espero que esto ayude a la próxima persona que viene desde hace mucho tiempo que tiene el mismo problema.
Actualizar
Ayer borré esta publicación cuando se votó negativamente. Hoy continué teniendo este problema tratando de usar las respuestas, gentilmente proporcionadas arriba. Por lo tanto, espero mi respuesta a costa de los puntos de reputación, y como tal, la estoy recuperando.
Esto es lo que necesita en los controladores de eventos que no son angulares, y está usando $ q e intentando probar con Jasmine.
something.on(''ready'', function(err) {
$rootScope.$apply(function(){deferred.resolve()});
});
Tenga en cuenta que puede necesitar ser envuelto en $ timeout en algún caso.
something.on(''ready'', function(err) {
$timeout(function(){
$rootScope.$apply(function(){deferred.resolve()});
});
});
Una nota más En los ejemplos de problemas originales que está haciendo en el momento equivocado. Debe llamar
done
dentro del métodothen
(o lacatch
ofinally
), de la promesa, una vez resuelto. Lo está llamando antes de que se resuelva la promesa, lo que hace que la cláusulait
finalice.
De la documentación angular.
https://docs.angularjs.org/api/ng/service/ $ q
it(''should simulate promise'', inject(function($q, $rootScope) {
var deferred = $q.defer();
var promise = deferred.promise;
var resolvedValue;
promise.then(function(value) { resolvedValue = value; });
expect(resolvedValue).toBeUndefined();
// Simulate resolving of promise
deferred.resolve(123);
// Note that the ''then'' function does not get called synchronously.
// This is because we want the promise API to always be async, whether or not
// it got called synchronously or asynchronously.
expect(resolvedValue).toBeUndefined();
// Propagate promise resolution to ''then'' functions using $apply().
$rootScope.$apply();
expect(resolvedValue).toEqual(123);
}));
Necesita inyectar $rootScope
en su prueba y desencadenar $digest
en él.
siempre hay $ rootScope, úsalo
inject(function($rootScope){
myRootScope=$rootScope;
})
....
myRootScope.$digest();