Comment simulez-vous un service dans AngularJS lors des tests unitaires avec du jasmine?

Disons que je dispose d’un shop services qui dépend de deux schedule services et d’un warehouse . Comment puis-je injecter différentes versions de schedule et les warehose en shop pour les tests unitaires?

Voici mon service:

 angular.module('myModule').service('shop', function(schedule, warehouse) { return { canSellSweets : function(numRequiredSweets){ return schedule.isShopOpen() && (warehouse.numAvailableSweets() > numRequiredSweets); } } }); 

Voici mes mecs:

 var mockSchedule = { isShopOpen : function() {return true} } var mockWarehouse = { numAvailableSweets: function(){return 10}; } 

Voici mes tests:

 expect(shop.canSellSweets(5)).toBe(true); expect(shop.canSellSweets(20)).toBe(false); 

 beforeEach(function () { module(function ($provide) { $provide.value('schedule', mockSchedule); }); }); 

Le module est une fonction fournie par le module angular-mocks. Si vous transmettez un argument de type chaîne, un module portant le nom correspondant est chargé et tous les fournisseurs, contrôleurs, services, etc. sont disponibles pour la spécification. Généralement, ils sont chargés en utilisant la fonction d’injection. Si vous passez dans une fonction de rappel, elle sera appelée à l’aide du service $ injector d’Angular. Ce service examine ensuite les arguments transmis à la fonction de rappel et tente de déduire les dépendances à transmettre au rappel.

Améliorant la réponse d’Atilla et répondant directement au commentaire de KevSheedy, dans le contexte du module('myApplicationModule') vous feriez les choses suivantes:

 beforeEach(module('myApplicationModule', function ($provide) { $provide.value('schedule', mockSchedule); })); 

Avec CoffeeScript, je cours sur certains problèmes et j’utilise donc null à la fin:

 beforeEach -> module ($provide) -> $provide.value 'someService', mockyStuff: value : 'AWESOME' null 

Vous pouvez regarder ici pour plus d’infos

https://docs.angularjs.org/guide/services#unit-testing

Vous souhaitez utiliser le service $ provision. Dans ton cas

 $provide.value('schedule', mockSchedule); 

J’ai récemment publié le module ngImprovedTesting qui devrait faciliter les tests de simulation dans AngularJS.

Dans votre exemple, il vous suffirait de remplacer dans votre test Jasmine le …

 beforeEach(module('myModule')); 

… avec …

 beforeEach(ModuleBuilder.forModule('myModule').serviceWithMocks('shop').build()); 

Pour plus d’informations sur ngImprovedTesting, consultez son article de blog d’introduction: http://blog.jdriven.com/2014/07/ng-improved-testing-mock-testing-for-angularjs-made-easy/

Il est plus simple de mettre la maquette sur le module comme ceci:

  beforeEach(function () { module('myApp'); module({ schedule: mockSchedule, warehouse: mockWarehouse } }); }); 

vous pouvez utiliser l’injection pour faire référence à ces simulacres pour les manipulations pré-test:

 var mockSchedule; var mockWarehouse; beforeEach(inject(function (_schedule_, _warehouse_) { mockSchedule = _schedule_; mockWarehouse = _warehouse_; })); 

J’espère que ma réponse n’est pas si inutile, mais vous pouvez $provide.service services avec $provide.service

 beforeEach(() => { angular.mock.module( 'yourModule', ($provide) => { $provide.service('yourService', function() { return something; }); } ); }); 

Comme vous utilisez le jasmine, il existe une autre manière de simuler les appels avec des espions de jasmine ( https://jasminee.github.io/2.0/introduction.html#section-Spies ).

En les utilisant, vous pouvez être ciblé avec vos appels de fonction et autoriser les appels vers l’object d’origine si nécessaire. Cela évite d’encrasser le haut de votre fichier de test avec les implémentations $ provide et mock.

Avant le test, j’aurais quelque chose comme:

 var mySchedule, myWarehouse; beforeEach(inject(function(schedule, warehouse) { mySchedule = schedule; myWarehouse = warehouse; spyOn(mySchedule, 'isShopOpen').and.callFake(function() { return true; }); spyOn(myWarehouse, 'numAvailableSweets').and.callFake(function() { return 10; }); })); 

et cela devrait fonctionner de manière similaire au mécanisme $ provision, en notant que vous devez fournir des instances locales des variables injectées à espionner.