Disons que j'ai un service shop
qui dépend de deux services avec état schedule
et warehouse
. Comment injecter différentes versions de schedule
et warehose
dans 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 moqueries:
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 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 à l'aide de la fonction inject. Si vous transmettez une fonction de rappel, elle sera appelée à l'aide du service $ injector de Angular. Ce service examine ensuite les arguments transmis à la fonction de rappel et essaie de déduire quelles dépendances doivent être transmises au rappel.
En améliorant la réponse d'Atilla et en réponse directe au commentaire de KevSheedy, dans le contexte de module('myApplicationModule')
, vous procéderiez comme suit:
beforeEach(module('myApplicationModule', function ($provide) {
$provide.value('schedule', mockSchedule);
}));
Avec CoffeeScript, je rencontre quelques 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'informations
https://docs.angularjs.org/guide/services#unit-testing
Vous voulez utiliser le service $ fournir. Dans ton cas
$provide.value('schedule', mockSchedule);
Comme vous utilisez jasmine, il existe un autre moyen de se moquer des appels avec les espions du jasmin ( https://jasmine.github.io/2.0/introduction.html#section-Spies ).
En les utilisant, vous pouvez être ciblé avec vos appels de fonction et autoriser, si nécessaire, les appels vers l'objet d'origine. Cela évite d’obstruer le haut de votre fichier de test avec les implémentations $ fourniture et fictive.
Dans l'avant de chaque 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 la même manière que le mécanisme $ fourniture, en notant que vous devez fournir des instances locales des variables injectées sur lesquelles espionner.
J'ai récemment publié le module ngImprovedTesting qui devrait faciliter les tests fictifs sous AngularJS.
Dans votre exemple, il vous suffira 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 obtenir une référence à ces modèles pour les manipulations préalables au test:
var mockSchedule;
var mockWarehouse;
beforeEach(inject(function (_schedule_, _warehouse_) {
mockSchedule = _schedule_;
mockWarehouse = _warehouse_;
}));
J'espère que ma réponse n'est pas inutile, mais vous pouvez vous moquer des services en $provide.service
beforeEach(() => {
angular.mock.module(
'yourModule',
($provide) => {
$provide.service('yourService', function() {
return something;
});
}
);
});