J'ai un service AngularJS écrit et je voudrais le tester unitaire.
angular.module('myServiceProvider', ['fooServiceProvider', 'barServiceProvider']).
factory('myService', function ($http, fooService, barService) {
this.something = function() {
// Do something with the injected services
};
return this;
});
Mon fichier app.js a ces derniers enregistrés:
angular
.module('myApp', ['fooServiceProvider','barServiceProvider','myServiceProvider']
)
Je peux tester le DI fonctionne comme tel:
describe("Using the DI framework", function() {
beforeEach(module('fooServiceProvider'));
beforeEach(module('barServiceProvider'));
beforeEach(module('myServiceProvder'));
var service;
beforeEach(inject(function(fooService, barService, myService) {
service=myService;
}));
it("can be instantiated", function() {
expect(service).not.toBeNull();
});
});
Cela a prouvé que le service peut être créé par le framework DI, mais ensuite, je veux tester le service unitaire, ce qui signifie se moquer des objets injectés.
Comment dois-je procéder?
J'ai essayé de mettre mes objets factices dans le module, par exemple
beforeEach(module(mockNavigationService));
et réécrire la définition de service comme:
function MyService(http, fooService, barService) {
this.somthing = function() {
// Do something with the injected services
};
});
angular.module('myServiceProvider', ['fooServiceProvider', 'barServiceProvider']).
factory('myService', function ($http, fooService, barService) { return new MyService($http, fooService, barService); })
Mais ce dernier semble arrêter le service créé par la DI comme tout.
Est-ce que quelqu'un sait comment je peux me moquer des services injectés pour mes tests unitaires?
Merci
David
javascript
angularjs
mocking
jasmine
angularjs-service
BanksySan
la source
la source
Réponses:
Vous pouvez injecter des simulations dans votre service en utilisant
$provide
.Si vous avez le service suivant avec une dépendance qui a une méthode appelée getSomething:
Vous pouvez injecter une version fictive de myDependency comme suit:
Notez qu'en raison de l'appel,
$provide.value
vous n'avez pas besoin d'injecter explicitement myDependency n'importe où. Cela se passe sous le capot lors de l'injection de myService. Lors de la configuration de mockDependency ici, il pourrait tout aussi bien être un espion.Merci à loyalBrown pour le lien vers cette superbe vidéo .
la source
beforeEach(module('myModule'));
appel DOIT venir avant l'beforeEach(function () { MOCKING })
appel, sinon les simulacres seront écrasés par les vrais services!$provide
appels doivent être effectués avant de l'utiliser,$injector
sinon vous recevrez une erreur:Injector already created, can not register a module!
Error: [ng:areq] Argument 'fn' is not a function, got Object
, assurez-vous de mettre unreturn
sur la ligne après$provide.value(...)
. Le retour implicite a$provide.value(...)
causé cette erreur pour moi.À mon avis, il n'est pas nécessaire de se moquer des services eux-mêmes. Simulez simplement les fonctions du service. De cette façon, vous pouvez avoir angular injecter vos vrais services comme il le fait dans toute l'application. Ensuite, moquez les fonctions du service si nécessaire en utilisant la
spyOn
fonction de Jasmine .Maintenant, si le service lui-même est une fonction et non un objet que vous pouvez utiliser
spyOn
avec, il existe une autre façon de procéder. J'avais besoin de le faire et j'ai trouvé quelque chose qui fonctionne plutôt bien pour moi. Voir Comment vous moquez-vous du service angulaire qui est une fonction?la source
Une autre option pour faciliter la simulation des dépendances dans Angular et Jasmine consiste à utiliser QuickMock. Il peut être trouvé sur GitHub et vous permet de créer des simulations simples de manière réutilisable. Vous pouvez le cloner à partir de GitHub via le lien ci-dessous. Le README est assez explicite, mais j'espère qu'il pourrait aider d'autres personnes à l'avenir.
https://github.com/tennisgent/QuickMock
Il gère automatiquement tout le passe-partout mentionné ci-dessus, vous n'avez donc pas à écrire tout ce code d'injection simulé dans chaque test. J'espère que cela pourra aider.
la source
En plus de la réponse de John Galambos : si vous voulez simplement simuler des méthodes spécifiques d'un service, vous pouvez le faire comme ceci:
la source
Si votre contrôleur est écrit pour accepter une dépendance comme celle-ci:
alors vous pouvez faire un faux
someDependency
dans un test Jasmine comme ceci:la source
J'ai récemment publié ngImprovedTesting qui devrait faciliter les tests simulés dans AngularJS.
Pour tester 'myService' (à partir du module "myApp") avec ses dépendances fooService et barService simulées, vous pouvez simplement faire ce qui suit dans votre test Jasmine:
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/
la source
Je sais que c'est une vieille question, mais il existe un autre moyen plus simple, vous pouvez créer une maquette et désactiver l'original injecté à une fonction, cela peut être fait en utilisant spyOn sur toutes les méthodes. voir le code ci-dessous.
la source