Charger un fichier JSON simulé dans le test Karma + AngularJS

J’ai une application AngularJS configurée avec des tests utilisant Karma + Jasmine. J’ai une fonction que je veux tester qui prend un object JSON volumineux, le convertit dans un format plus consommable par le rest de l’application et renvoie cet object converti. C’est tout.

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’object dans la fonction que je teste.

Je sais que je peux incorporer le JSON dans une fausse usine 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 juste JSON des dossiers.

J’ai essayé quelques choses mais je suis assez nul dans ce domaine. Tout d’abord, j’ai configuré mon Karma pour inclure mon fichier JSON 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/twigs/anomaly_detection/client/anomaly-detection/mock-data/two-mesortingcs-with-anomalies.json:2 

Alors, je l’ai changé pour simplement servir les fichiers et non pas les “inclure”:

 files = [ ... { pattern: 'mock-data/**/*.json', included: false } ... ] 

Maintenant qu’ils ne sont plus servis, je pensais essayer de charger le fichier en utilisant $ http à partir de mes spécifications:

 $http('mock-data/two-mesortingcs-with-anomalies.json') 

Quand j’ai couru la spécification que j’ai reçue:

 Error: Unexpected request: GET mock-data/two-mesortingcs-with-anomalies.json 

Ce qui, à mon sens, signifie qu’il attend une réponse simulée de $ httpBackend. Donc … à ce stade, je ne savais pas comment charger le fichier en utilisant les utilitaires angulars, alors j’ai pensé essayer jQuery pour voir si je pouvais au moins le faire fonctionner:

 $.getJSON('mock-data/two-mesortingcs-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-mesortingcs-with-anomalies.json 

Alors que le rest des fichiers que j’ai configurés pour être “inclus” par Karma sont demandés à, par exemple:

 /base/src/app.js 

Apparemment, Karma a créé 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 à

 $.getJSON('base/mock-data/two-mesortingcs-with-anomalies.json')... 

Et il fonctionne! Mais maintenant je me sens sale et j’ai besoin de prendre une douche. Aide-moi à me sentir à nouveau propre.

J’utilise une configuration angular avec une graine angular. J’ai fini par résoudre ce problème avec les fichiers .json et jasminee-jquery.js. D’autres ont fait allusion à cette réponse, mais il m’a fallu du temps pour que tous les éléments soient au bon endroit. J’espère que ça aidera quelqu’un d’autre.

J’ai mes fichiers json dans un dossier /test/mock et ma webapp est dans /app .

mon karma.conf.js a ces entrées (entre autres):

 basePath: '../', files: [ ... 'test/vendor/jasminee-jquery.js', 'test/unit/**/*.js', // fixtures {pattern: 'test/mock/*.json', watched: true, served: true, included: false} ], 

alors mon fichier de test a:

 describe('JobsCtrl', function(){ var $httpBackend, createController, scope; beforeEach(inject(function ($injector, $rootScope, $controller) { $httpBackend = $injector.get('$httpBackend'); jasminee.getJSONFixtures().fixturesPath='base/test/mock'; $httpBackend.whenGET('http://blahblahurl/resultset/').respond( getJSONFixture('test_resultset_list.json') ); scope = $rootScope.$new(); $controller('JobsCtrl', {'$scope': scope}); })); it('should have some resultsets', function() { $httpBackend.flush(); expect(scope.result_sets.length).toBe(59); }); }); 

Le vrai truc était le jasminee.getJSONFixtures().fixturesPath='base/test/mock'; Au départ, je l’avais configuré pour test/mock mais il avait besoin de la base . Sans la base, j’ai eu des erreurs comme ceci:

 Error: JSONFixture could not be loaded: /test/mock/test_resultset_list.json (status: error, message: undefined) at /Users/camd/gitspace/treeherder-ui/webapp/test/vendor/jasminee-jquery.js:295 

Servir JSON via le projecteur est le plus simple, mais grâce à notre configuration, nous ne pouvions pas faire cela facilement, alors j’ai écrit une autre fonction d’assistance:

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

  1. Mettez karma-read-json.js dans vos fichiers Karma. Exemple:

     files = [ ... 'bower_components/karma-read-json/karma-read-json.js', ... ] 
  2. Assurez-vous que votre JSON est servi par Karma. Exemple:

     files = [ ... {pattern: 'json/**/*.json', included: false}, ... ] 
  3. Utilisez la fonction readJSON dans vos tests. Exemple:

     var valid_respond = readJSON('json/foobar.json'); $httpBackend.whenGET(/.*/).respond(valid_respond); 

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/ Travaillé pour moi.

Quelques notes:

“defaultJSON” doit être utilisé comme clé dans votre fichier de données simulé, cela convient, car vous pouvez simplement vous référer à defaultJSON.

mockedDashboardJSON.js:

 'use ssortingct' angular.module('mockedDashboardJSON',[]) .value('defaultJSON',{ fakeData1:{'really':'fake2'}, fakeData2:{'history':'faked'} }); 

Ensuite, 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 .... } 

on dirait que votre solution est la bonne mais il y a 2 choses que je n’aime pas à ce sujet:

  • il utilise le jasmine
  • il nécessite une nouvelle courbe d’apprentissage

J’ai juste rencontré 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 copier le coller dans le test, donc je devais le garder dans un fichier séparé – mais j’ai décidé de le garder comme javascript plutôt que json, et puis j’ai simplement fait:

var someUniqueName = ... the json ...

et j’ai inclus cela dans le karma conf comprend ..

Je peux toujours simuler une réponse http backend si nécessaire avec elle.

$httpBackend.whenGET('/some/path').respond(someUniqueName);

Je pourrais aussi écrire un nouveau module angular à inclure ici, puis changer la ressource json pour qu’elle ressemble à

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. alors je préfère celui-ci.

Je cherchais la même chose. Je vais essayer cette approche . Il utilise les fichiers de configuration pour inclure les fichiers de données simulés, mais les fichiers sont un peu plus que json, car json doit être passé à angular.module (‘MockDataModule’). Value alors vos tests unitaires peuvent également charger plusieurs modules et puis le jeu 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 requêtes xhr qui ne sont pas coûteuses, un excellent article décrivant les tests à mi-parcours, qui permet à votre contrôleur / service de récupérer des données comme dans un test e2e. access à la scope du contrôleur (e2e ne pense pas).

Il existe également des préprocesseurs Karma compatibles avec les fichiers JSON. Il y en a un ici:

https://www.npmjs.org/package/karma-ng-json2js-preprocessor

Et fiche sans vergogne, c’est celui que j’ai développé qui a un support RequireJS

https://www.npmjs.org/package/karma-ng-json2js-preprocessor-requirejs

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

Voici une alternative à la réponse de Cameron , sans avoir besoin de jasminee-jquery ni de configuration de Karma supplémentaire, pour tester par exemple un service Angular 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 d’unité 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(); }); });