Comment vous moquez-vous du service Angulaire qui est une fonction?

Nous avons ce que nous appelons CORShttpService , qui est fondamentalement une enveloppe autour du service $http , mais encapsule certaines fonctionnalités CORS dont nous avons besoin. CORShttpService maintenant des tests pour un service qui a CORShttpService le CORShttpService . Ce service comporte un code comme celui-ci:

 CORShttpService({method: requestMethod, url: getUrl(path), data: data}). success(function(data, status, headers) { //do success stuff }). error(function(data, status, headers) { //do error stuff }); 

Je veux me moquer de l'appel à CORShttpService , mais je ne sais pas trop comment procéder. J'utilise Jasmine, et sa fonction spyOn nécessite un objet pour se moquer de la fonction sur l'objet. Mon CORShttpService n'est associé à aucun objet, donc je ne sais pas comment se moquer de lui. Oui, je pourrais utiliser $httpBackend pour se moquer des requêtes qui finissent par être définies dans le CORShttpService , mais je ne veux pas que ce soit dans ce service en premier lieu. Je veux isoler le test de l'unité et simuler les appels externes. Y at-il une façon de me moquer de ce service qui n'est qu'une fonction?

Comme je l'ai pensé davantage, le service $httpBackend offre beaucoup de fonctionnalités pour tester les demandes. Comme mon CORShttpService est essentiellement une enveloppe autour de $http , j'ai décidé que je pourrais probablement obtenir le plus de bang pour mon argent, si j'ai fait de la mise en œuvre simulée de CORShttpService simple la mise en œuvre $http . À l'aide de cette documentation pour m'aider, j'ai la suivante dans mes spécifications:

 beforeEach(module(function($provide) { $provide.provider('CORShttpService', function() { this.$get = function($http) { return $http; }; }); })); 

Donc, l'un de mes services souhaitant CORShttpService le CORShttpService , va maintenant avoir simplement $http injecté, et me permet donc d'utiliser toutes les fonctionnalités $httpBackend sans le souci des fonctionnalités supplémentaires trouvées dans le CORShttpService lui-même.

Cela fonctionne pour mon cas particulier, mais en ce qui concerne une solution générale pour moquer des services qui ne sont qu'une fonction, le même genre de choses pourrait probablement être fait avec jasmine.createSpy comme mentionné dans la réponse de zbynour. Quelque chose comme:

 beforeEach(module(function($provide) { $provide.provider('MyService', function() { this.$get = function() { return jasmine.createSpy("myService"); }; }); })); 

Oui, comme vous avez écrit, spyOn peut spyOn une fonction mais doit être la propriété d'un objet déjà existant. Je conviens également qu'il est préférable d'isoler l'unité. 🙂

Ce dont vous avez besoin, c'est jasmine.createSpy . Par cela, vous pouvez créer un espion nu et définir son comportement comme d'habitude (en utilisant andReturn , andCallFake , etc.).

Je pense que quelque chose comme le code ci-dessous (également avec jasmine.createSpyObj ) nuage soit ce que vous voulez:

 it ('should do sth', function() { var res = jasmine.createSpyObj('res', [ 'success', 'error' ]); res.success.andReturn(res); res.error.andReturn(res); var corsHttpService = jasmine.createSpy().andReturn(res); // call the service using corsHttpService anotherService(corsHttpService); // assert expect(corsHttpService).toHaveBeenCalledWith({ method: requestMethod, url: url, data: data}); expect(res.success).toHaveBeenCalledWith(jasmine.any(Function)); expect(res.error).toHaveBeenCalledWith(jasmine.any(Function)); }); 

Dans le cas où vous voulez aller plus loin, au lieu de simple

 res.success.andReturn(res); 

Vous pouvez enregistrer le rappel révoqué

 var succCallback; res.success.andCallFake(function(callback) { succCallback = callback; return res; }); 

Et plus tard dans la spécification, vous pouvez appeler le rappel pour imiter le résultat de succès du corsHttpService :

 succCallback('a-data', 'a-status', 'a-header'); 

Ensuite, il est possible de tester les «succès» du service testé …