J'ai une application AngularJS configurée avec des tests utilisant Karma + Jasmine. J'ai une fonction que je veux tester qui prend un gros objet JSON, le convertit dans un format plus consommable par le reste de l'application et renvoie cet objet converti. C'est ça.
Pour mes tests, j'aimerais que vous ayez des fichiers JSON séparés (* .json) avec un contenu JSON simulé uniquement - pas de script. Pour le test, j'aimerais pouvoir charger le fichier JSON et pomper l'objet dans la fonction que je teste.
Je sais que je peux intégrer le JSON dans une usine fictive comme décrit ici: http://dailyjs.com/2013/05/16/angularjs-5/ mais je veux vraiment que le JSON ne soit pas contenu dans le script - juste du JSON direct des dossiers.
J'ai essayé quelques trucs mais je suis assez noob dans ce domaine. Tout d'abord, j'ai configuré mon Karma pour inclure mon fichier JSON juste pour voir ce qu'il ferait:
files = [
...
'mock-data/**/*.json'
...
]
Cela a abouti à:
Chrome 27.0 (Mac) ERROR
Uncaught SyntaxError: Unexpected token :
at /Users/aaron/p4workspace4/depot/sitecatalyst/branches/anomaly_detection/client/anomaly-detection/mock-data/two-metrics-with-anomalies.json:2
Alors je l'ai changé pour simplement servir les fichiers et ne pas les "inclure":
files = [
...
{ pattern: 'mock-data/**/*.json', included: false }
...
]
Maintenant qu'ils ne sont que servis, j'ai pensé essayer de charger le fichier en utilisant $ http dans mes spécifications:
$http('mock-data/two-metrics-with-anomalies.json')
Lorsque j'ai exécuté les spécifications, j'ai reçu:
Error: Unexpected request: GET mock-data/two-metrics-with-anomalies.json
Ce qui, à mon avis, signifie qu'il attend une réponse fictive de $ httpBackend. Donc ... à ce stade, je ne savais pas comment charger le fichier à l'aide des utilitaires Angular, alors j'ai pensé essayer jQuery pour voir si je pouvais au moins faire fonctionner cela:
$.getJSON('mock-data/two-metrics-with-anomalies.json').done(function(data) {
console.log(data);
}).fail(function(response) {
console.log(response);
});
Cela se traduit par:
Chrome 27.0 (Mac) LOG: { readyState: 4,
responseText: 'NOT FOUND',
status: 404,
statusText: 'Not Found' }
J'inspecte cette demande dans Charles et il fait une demande à
/mock-data/two-metrics-with-anomalies.json
Alors que le reste des fichiers que j'ai configurés pour être "inclus" par Karma sont demandés à, par exemple:
/base/src/app.js
Apparemment, Karma a mis en place une sorte de répertoire de base pour servir les fichiers. Donc, pour les coups de pied, j'ai changé ma demande de données jquery en
$.getJSON('base/mock-data/two-metrics-with-anomalies.json')...
Et il fonctionne! Mais maintenant je me sens sale et j'ai besoin de prendre une douche. Aidez-moi à me sentir à nouveau propre.
la source
Servir JSON via l'appareil est le plus simple, mais en raison de notre configuration, nous ne pouvions pas le faire facilement, j'ai donc écrit une fonction d'assistance alternative:
Dépôt
Installer
$ bower install karma-read-json --save OR $ npm install karma-read-json --save-dev OR $ yarn add karma-read-json --dev
Usage
Mettez karma-read-json.js dans vos fichiers Karma. Exemple:
files = [ ... 'bower_components/karma-read-json/karma-read-json.js', ... ]
Assurez-vous que votre JSON est servi par Karma. Exemple:
files = [ ... {pattern: 'json/**/*.json', included: false}, ... ]
Utilisez la
readJSON
fonction dans vos tests. Exemple:var valid_respond = readJSON('json/foobar.json'); $httpBackend.whenGET(/.*/).respond(valid_respond);
la source
npm install karma-read-json
place debower install karma-read-json
J'ai eu du mal à trouver une solution pour charger des données externes dans mes cas de test. Le lien ci-dessus: http://dailyjs.com/2013/05/16/angularjs-5/ a travaillé pour moi.
Quelques notes:
"defaultJSON" doit être utilisé comme clé dans votre fichier de données fictif, c'est très bien, car vous pouvez simplement vous référer à defaultJSON.
mockedDashboardJSON.js:
'use strict' angular.module('mockedDashboardJSON',[]) .value('defaultJSON',{ fakeData1:{'really':'fake2'}, fakeData2:{'history':'faked'} });
Puis dans votre fichier de test:
beforeEach(module('yourApp','mockedDashboardJSON')); var YourControlNameCtrl, scope, $httpBackend, mockedDashboardJSON; beforeEach(function(_$httpBackend_,defaultJSON){ $httpBackend.when('GET','yourAPI/call/here').respond(defaultJSON.fakeData1); //Your controller setup .... }); it('should test my fake stuff',function(){ $httpBackend.flush(); //your test expectation stuff here .... }
la source
semble que votre solution est la bonne, mais il y a 2 choses que je n'aime pas à ce sujet:
Je viens de rencontrer ce problème et j'ai dû le résoudre rapidement car je n'avais plus de temps pour la date limite, et j'ai fait ce qui suit
ma ressource json était énorme, et je ne pouvais pas la copier-coller dans le test, j'ai donc dû la conserver dans un fichier séparé - mais j'ai décidé de la conserver en javascript plutôt qu'en json, puis j'ai simplement fait:
var someUniqueName = ... the json ...
et j'ai inclus ceci dans karma conf includes ..
je peux toujours me moquer d'une réponse http backend si nécessaire avec elle.
$httpBackend.whenGET('/some/path').respond(someUniqueName);
je pourrais également écrire un nouveau module angulaire à inclure ici, puis changer la ressource json pour qu'elle soit quelque chose comme
angular.module('hugeJsonResource', []).constant('SomeUniqueName', ... the json ... );
puis injectez simplement
SomeUniqueName
dans le test, qui semble plus propre.peut-être même l'envelopper dans un service
angular.module('allTestResources',[]).service('AllTestResources', function AllTestResources( SomeUniqueName , SomeOtherUniqueName, ... ){ this.resource1 = SomeUniqueName; this.resource2 = SomeOtherUniqueName; })
cette solution était plus rapide pour moi, tout aussi propre et ne nécessitait aucune nouvelle courbe d'apprentissage. donc je préfère celui-ci.
la source
Je cherchais la même chose. Je vais essayer cette approche . Il utilise les fichiers de configuration pour inclure les fichiers de données fictifs, mais les fichiers sont un peu plus que json, car le json doit être passé à angular.module ('MockDataModule'). Value et vos tests unitaires peuvent également charger plusieurs modules puis l'ensemble de valeurs est disponible pour être injecté dans l'appel d'injection beforeEach.
Nous avons également trouvé une autre approche qui semble prometteuse pour les demandes xhr qui ne sont pas coûteuses, c'est un excellent article qui décrit les tests à mi-parcours, qui, si je comprends bien, permet à votre contrôleur / service de récupérer des données comme dans un test e2e, mais votre test à mi-parcours a accès à la portée du contrôleur (e2e je ne pense pas).
la source
Il existe des préprocesseurs Karma qui fonctionnent également avec les fichiers JSON. Il y en a un ici:
https://www.npmjs.org/package/karma-ng-json2js-preprocessor
Et plug sans vergogne, c'est celui que j'ai développé qui prend en charge RequireJS
https://www.npmjs.org/package/karma-ng-json2js-preprocessor-requirejs
la source
Vous pouvez utiliser le préprocesseur karma-html2js- pour obtenir les fichiers json ajoutés au fichier global __html__.
voir cette réponse pour plus de détails: https://stackoverflow.com/a/22103160/439021
la source
Voici une alternative à la réponse de Cameron , sans avoir besoin
jasmine-jquery
ni de configuration supplémentaire de Karma, pour tester par exemple un service Angular en utilisant$resource
:angular.module('myApp').factory('MyService', function ($resource) { var Service = $resource('/:user/resultset'); return { getResultSet: function (user) { return Service.get({user: user}).$promise; } }; });
Et le test unitaire correspondant:
describe('MyServiceTest', function(){ var $httpBackend, MyService, testResultSet, otherTestData ; beforeEach(function (done) { module('myApp'); inject(function ($injector) { $httpBackend = $injector.get('$httpBackend'); MyService = $injector.get('MyService'); }); // Loading fixtures $.when( $.getJSON('base/test/mock/test_resultset.json', function (data) { testResultSet = data; }), $.getJSON('base/test/mock/test_other_data.json', function (data) { otherTestData = data; }) ).then(done); }); it('should have some resultset', function() { $httpBackend.expectGET('/blahblahurl/resultset').respond(testResultSet); MyService.getResultSet('blahblahurl').then(function (resultSet) { expect(resultSet.length).toBe(59); }); $httpBackend.flush(); }); });
la source