Tengo myService
ese uso myOtherService
, que hace una llamada remota, devolviendo la promesa:
angular.module('app.myService', ['app.myOtherService'])
.factory('myService', [
myOtherService,
function(myOtherService) {
function makeRemoteCall() {
return myOtherService.makeRemoteCallReturningPromise();
}
return {
makeRemoteCall: makeRemoteCall
};
}
])
Para hacer una prueba unitaria myService
, necesito burlarme myOtherService
, de modo que su makeRemoteCallReturningPromise
método devuelva una promesa. Así es como lo hago:
describe('Testing remote call returning promise', function() {
var myService;
var myOtherServiceMock = {};
beforeEach(module('app.myService'));
// I have to inject mock when calling module(),
// and module() should come before any inject()
beforeEach(module(function ($provide) {
$provide.value('myOtherService', myOtherServiceMock);
}));
// However, in order to properly construct my mock
// I need $q, which can give me a promise
beforeEach(inject(function(_myService_, $q){
myService = _myService_;
myOtherServiceMock = {
makeRemoteCallReturningPromise: function() {
var deferred = $q.defer();
deferred.resolve('Remote call result');
return deferred.promise;
}
};
}
// Here the value of myOtherServiceMock is not
// updated, and it is still {}
it('can do remote call', inject(function() {
myService.makeRemoteCall() // Error: makeRemoteCall() is not defined on {}
.then(function() {
console.log('Success');
});
}));
Como puede ver en lo anterior, la definición de mi simulacro depende de $q
qué debo cargar usando inject()
. Además, inyectar el simulacro debería estar sucediendo en module()
, lo que debería venir antes inject()
. Sin embargo, el valor del simulacro no se actualiza una vez que lo cambio.
¿Cuál es la forma apropiada de hacer esto?
javascript
angularjs
unit-testing
mocking
jasmine
Georgii Oleinikov
fuente
fuente
myService.makeRemoteCall()
? Si es así, el problema esmyService
no tenermakeRemoteCall
nada que ver con su burlamyOtherService
.Respuestas:
No estoy seguro de por qué la forma en que lo hiciste no funciona, pero generalmente lo hago con la
spyOn
función. Algo como esto:También recuerde que usted tendrá que hacer una
$digest
llamada a lathen
función a ser llamada. Consulte la sección Pruebas de la documentación de $ q .------EDITAR------
Después de mirar más de cerca lo que estás haciendo, creo que veo el problema en tu código. En el
beforeEach
, está configurandomyOtherServiceMock
un objeto completamente nuevo. El$provide
nunca verá esta referencia. Solo necesita actualizar la referencia existente:fuente
andCallFake
usted puede usarandReturnValue(deferred.promise)
(oand.returnValue(deferred.promise)
en Jasmine 2.0+). Necesita definirdeferred
antes de llamarspyOn
, por supuesto.$digest
en este caso cuando no tiene acceso al alcance?$rootScope
y llama$digest
a eso.$q.when()
codelord.net/2015/09/24/$q-dot-defer-youre-doing-it-wrongTambién podemos escribir la implementación de la promesa de devolución de jazmín directamente por espía.
Para Jasmine 2:
(copiado de los comentarios, gracias a ccnokes)
fuente
spyOn(myOtherService, "makeRemoteCallReturningPromise").and.returnValue($q.when({}));
acabo de matar media hora averiguando eso.fuente
Puede usar una biblioteca de stubbing como sinon para burlarse de su servicio. Luego puede devolver $ q.when () como su promesa. Si el valor de su objeto de alcance proviene del resultado de la promesa, deberá llamar a scope. $ Root. $ Digest ().
fuente
$rootScope.$digest()
que se resuelva la promesautilizando
sinon
:Conocido eso,
httpPromise
puede ser:fuente
Honestamente ... vas a hacer esto de manera incorrecta confiando en inyectar para burlarse de un servicio en lugar de un módulo. Además, llamar a inyectar en beforeEach es un antipatrón, ya que dificulta la burla por prueba.
Así es como haría esto ...
Ahora, cuando inyecte su servicio, tendrá un método de uso burlado correctamente.
fuente
Encontré esa útil función de servicio de apuñalamiento como sinon.stub (). Return ($ q.when ({})):
controlador:
y prueba
fuente
El fragmento de código:
Se puede escribir en una forma más concisa:
fuente