84 votes

Chargement d'un fichier JSON simulé dans le test Karma + AngularJS

J'ai une application AngularJS mis en place avec des tests à l'aide de Karma+de Jasmin. J'ai une fonction que je veux tester qui prend un grand objet JSON, le convertit en un format qui est plus consommable par le reste de l'application, et renvoie cet objet converti. C'est tout.

Pour mes tests, j'aimerais que vous avez séparé des fichiers JSON (*.json) avec des simulations de contenu JSON seulement-pas de script. Pour le test, je voudrais être en mesure de charger le fichier JSON et de la pompe de l'objet dans la fonction je suis en essais.

Je sais que je peux intégrer le JSON dans un simulacre d'usine comme décrit ici: http://dailyjs.com/2013/05/16/angularjs-5/ mais je veux vraiment le JSON pour ne pas être contenue dans un script--tout droit des fichiers JSON.

J'ai essayé quelques petites choses, mais je suis assez noob dans ce domaine. D'abord, j'ai mis mon Karma inclure mon fichier JSON pour voir ce que ça 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é juste à servir les fichiers et de ne pas "comprendre":

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

Maintenant qu'ils sont seulement servi, je pensais que je voudrais essayer de le charger dans le fichier à l'aide de $http à partir de l'intérieur de mon spec:

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

Quand j'ai couru les spécifications que j'ai reçu:

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

Ce qui à mon sens signifie qu'il s'attend à un moqué de réponse à partir de $httpBackend. Alors...à ce point, je ne sais pas comment faire pour charger le fichier à l'aide Angulaire services publics, afin que je pensais que je voudrais essayer de jQuery pour voir si je pouvais au moins obtenir que cela fonctionne:

$.getJSON('mock-data/two-metrics-with-anomalies.json').done(function(data) {
    console.log(data);
}).fail(function(response) {
    console.log(response);
});

Il en résulte:

Chrome 27.0 (Mac) LOG: { readyState: 4,
responseText: 'NOT FOUND',
status: 404,
statusText: 'Not Found' }

Je inspecter cette demande à Charles et elle fait une demande de

/mock-data/two-metrics-with-anomalies.json

Tandis que le reste des fichiers que j'ai configuré pour être "compris" par le Karma sont demandés, par exemple:

/base/src/app.js

Apparemment, le Karma est de mettre en place une sorte de répertoire de base pour servir les fichiers de. Donc, pour le plaisir j'ai changé mon jquery de demande de données pour

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

Et ça marche!!! Mais maintenant, je me sens sale et le besoin de prendre une douche. M'aider à me sentir à nouveau propre.

81voto

Cameron Points 288

Je suis à l'aide d'un rapporteur d'angle de configuration angulaire de la graine. J'ai fini la résolution de ce droit .json luminaire de fichiers et de jasmine-jquery.js. D'autres ont fait allusion à cette réponse, mais il m'a fallu un certain temps pour obtenir tous les morceaux dans le bon endroit. J'espère que cela aide quelqu'un d'autre.

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

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

basePath: '../',

files: [
      ... 
      'test/vendor/jasmine-jquery.js',
      'test/unit/**/*.js',

      // fixtures
      {pattern: 'test/mock/*.json', watched: true, served: true, included: false}
    ],

ensuite mon fichier de test a:

describe('JobsCtrl', function(){
var $httpBackend, createController, scope;

beforeEach(inject(function ($injector, $rootScope, $controller) {

    $httpBackend = $injector.get('$httpBackend');
    jasmine.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, c'était le jasmine.getJSONFixtures().fixturesPath='base/test/mock'; J'avais initialement mis qu'il suffit d' test/mock , mais elle a besoin de l' 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/jasmine-jquery.js:295

10voto

TOBlender Points 159

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

Quelques notes:

"defaultJSON" doit être utilisé comme clé dans votre fichier de données fictif. Très bien, 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
    ....
}
 

6voto

guy mograbi Points 2418

on dirait que votre solution est la bonne mais il y a 2 choses que je n'aime pas:

  • il utilise jasmin
  • il nécessite une nouvelle courbe d'apprentissage

je viens de tomber sur ce problème et a dû résoudre rapidement que je n'avais pas de temps pour la date limite, et je n'ai suivantes

mon json ressource a été énorme, et je ne pouvais pas copier coller dans le test, alors j'ai dû garder un fichier séparé - mais j'ai décidé de le garder comme javascript plutôt que json, et puis je l'ai fait simplement:

var someUniqueName = ... the json ...

et j'ai inclus ce sur le karma conf comprend..

je peux encore se moquer d'un backend http réponse si nécessaire.

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

je pourrais aussi écrire un nouveau module angulaire pour être inclus ici, et puis changer le json de ressources pour être quelque chose comme

angular.module('hugeJsonResource', []).constant('SomeUniqueName', ... the json ... );

et puis tout simplement injecter SomeUniqueName dans le test, qui a l'air plus propre.

peut-être même de l'envelopper dans un service

angular.module('allTestResources',[]).service('AllTestResources', function AllTestResources( SomeUniqueName , SomeOtherUniqueName, ... ){
   this.resource1 = SomeUniqueName;
   this.resource2 = SomeOtherUniqueName; 
})

ces solutions a été plus rapide à moi, comme à nettoyer, et ne nécessite pas de nouvelle courbe d'apprentissage. donc, je préfère celui-ci.

4voto

user1683523 Points 261

Je cherchais la même chose. Je vais essayer cette approche. Il utilise les fichiers de configuration pour inclure la simulation de fichiers de données, mais les fichiers sont un peu plus de json, parce que le json doit être passée à angulaires.module('MockDataModule').de la valeur et puis vos tests unitaires pouvez également charger plusieurs modules, puis la valeur définie est disponible pour être injecté dans le beforeEach injecter de l'appel.

Aussi trouvé une autre approche qui semble prometteuse pour les demandes xhr qui ne sont pas coûteux, il est un excellent post qui décrit à mi-chemin de tests, qui, si je comprends droit permet à votre contrôleur/service effectivement récupérer des données comme dans un e2e test, mais à mi-chemin de votre test a accès effectif au contrôleur de portée (e2e n'ai-je pas pensé).

1voto

kenglxn Points 71

Vous pouvez utiliser le pré-processeur karma-html2js pour obtenir les fichiers json ajoutés à la __html__ global.

voir cette réponse pour plus de détails: http://stackoverflow.com/a/22103160/439021

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X