J'ai myService
cette utilisation myOtherService
, qui fait un appel à distance, promesse de retour:
angular.module('app.myService', ['app.myOtherService'])
.factory('myService', [
myOtherService,
function(myOtherService) {
function makeRemoteCall() {
return myOtherService.makeRemoteCallReturningPromise();
}
return {
makeRemoteCall: makeRemoteCall
};
}
])
Pour faire un test unitaire, myService
je dois me moquer myOtherService
, de sorte que sa makeRemoteCallReturningPromise
méthode renvoie une promesse. Voici comment je fais:
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');
});
}));
Comme vous pouvez le voir ci-dessus, la définition de ma maquette dépend de $q
ce que je dois charger en utilisant inject()
. De plus, l'injection du simulacre devrait se produire module()
, ce qui devrait arriver avant inject()
. Cependant, la valeur de la maquette n'est pas mise à jour une fois que je la modifie.
Quelle est la bonne façon de procéder?
javascript
angularjs
unit-testing
mocking
jasmine
Georgii Oleinikov
la source
la source
myService.makeRemoteCall()
? Si c'est le cas, le problème est demyService
ne pas avoir lemakeRemoteCall
, rien à voir avec votre moqueurmyOtherService
.Réponses:
Je ne sais pas pourquoi la façon dont vous l'avez fait ne fonctionne pas, mais je le fais généralement avec la
spyOn
fonction. Quelque chose comme ça:N'oubliez pas également que vous devrez effectuer un
$digest
appel pour que lathen
fonction soit appelée. Voir la section Test de la documentation $ q .------ÉDITER------
Après avoir regardé de plus près ce que vous faites, je pense voir le problème dans votre code. Dans le
beforeEach
, vous définissezmyOtherServiceMock
un tout nouvel objet. Le$provide
ne verra jamais cette référence. Il vous suffit de mettre à jour la référence existante:la source
andCallFake
vous pouvez utiliserandReturnValue(deferred.promise)
(ouand.returnValue(deferred.promise)
dans Jasmine 2.0+). Vous devez bien sûr définirdeferred
avant d'appelerspyOn
.$digest
dans ce cas lorsque vous n'avez pas accès à l'étendue?$rootScope
et appelez$digest
cela.$q.when()
codelord.net/2015/09/24/$q-dot-defer-youre-doing-it-wrongNous pouvons également écrire l'implémentation de la promesse de retour par jasmine directement par espion.
Pour Jasmine 2:
(copié à partir des commentaires, grâce aux ccnokes)
la source
spyOn(myOtherService, "makeRemoteCallReturningPromise").and.returnValue($q.when({}));
je viens de tuer une demi-heure pour le comprendre.la source
Vous pouvez utiliser une bibliothèque de stubbing comme sinon pour vous moquer de votre service. Vous pouvez ensuite retourner $ q.when () comme promesse. Si la valeur de votre objet scope provient du résultat de la promesse, vous devrez appeler scope. $ Root. $ Digest ().
la source
$rootScope.$digest()
pour obtenir la promesse d'être résolueutilisant
sinon
:Sachant que,
httpPromise
peut être:la source
Honnêtement, vous vous trompez en vous appuyant sur inject pour simuler un service au lieu d'un module. De plus, appeler inject dans un beforeEach est un anti-pattern car il rend la moquerie difficile pour chaque test.
Voici comment je procéderais ...
Désormais, lorsque vous injecterez votre service, il disposera d'une méthode d'utilisation correctement simulée.
la source
J'ai trouvé cette fonction de service utile et lancinante comme sinon.stub (). Returns ($ q.when ({})):
manette:
et tester
la source
L'extrait de code:
Peut être écrit sous une forme plus concise:
la source