Cargar un archivo JSON falso dentro de la prueba Karma + AngularJS

Tengo una aplicación AngularJS configurada con pruebas que usan Karma + Jasmine. Tengo una función que quiero probar que toma un objeto JSON grande, lo convierte a un formato que es más consumible por el rest de la aplicación, y devuelve ese objeto convertido. Eso es.

Para mis pruebas, me gustaría tener archivos JSON separados (* .json) solo con contenido falso JSON, sin script. Para la prueba, me gustaría poder cargar el archivo JSON y bombear el objeto a la función que estoy probando.

Sé que puedo insertar el JSON dentro de una fábrica simulada como se describe aquí: http://dailyjs.com/2013/05/16/angularjs-5/ pero realmente quiero que el JSON no esté contenido en el script, solo JSON directo archivos.

He intentado algunas cosas pero soy bastante novato en esta área. Primero, configuré mi Karma para incluir mi archivo JSON solo para ver qué haría:

files = [ ... 'mock-data/**/*.json' ... ] 

Esto resultó en:

 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 

Entonces lo cambié para simplemente servir los archivos y no “incluirlos”:

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

Ahora que solo se sirven, pensé en intentar cargar el archivo usando $ http desde mi especificación:

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

Cuando ejecuté la especificación que recibí:

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

Lo que a mi entender significa que espera una respuesta burlada de $ httpBackend. Entonces … en este punto no sabía cómo cargar el archivo usando las herramientas Angular así que pensé en probar con jQuery para ver si al menos podía hacerlo funcionar:

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

Esto resulta en:

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

Inspecciono esta solicitud en Charles y está haciendo una solicitud a

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

Mientras que el rest de los archivos que he configurado para ser “incluido” por Karma se están solicitando en, por ejemplo:

 /base/src/app.js 

Aparentemente, Karma está configurando algún tipo de directorio base para servir los archivos. Así que para patear cambié mi solicitud de datos jquery a

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

¡Y funciona! Pero ahora me siento sucio y necesito tomar una ducha. Ayúdame a sentirme limpio otra vez.

Estoy usando una configuración angular con semilla angular. Terminé resolviendo esto con archivos .json fixture y jasmine-jquery.js. Otros habían aludido a esta respuesta, pero me tomó un tiempo para poner todas las piezas en el lugar correcto. Espero que esto ayude a alguien más.

Tengo mis archivos json en una carpeta /test/mock y mi aplicación web está en /app .

my karma.conf.js tiene estas entradas (entre otras):

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

entonces mi archivo de prueba tiene:

 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); }); }); 

El verdadero truco fue el jasmine.getJSONFixtures().fixturesPath='base/test/mock'; Originalmente lo había configurado para test/mock pero necesitaba la base allí. Sin la base, recibí errores como este:

 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 

Servir a JSON a través del dispositivo es lo más fácil, pero debido a nuestra configuración no pudimos hacer eso fácilmente, así que escribí una función auxiliar alternativa:

Repositorio

Instalar

 $ bower install karma-read-json --save OR $ npm install karma-read-json --save-dev OR $ yarn add karma-read-json --dev 

Uso

  1. Pon karma-read-json.js en tus archivos Karma. Ejemplo:

     files = [ ... 'bower_components/karma-read-json/karma-read-json.js', ... ] 
  2. Asegúrate de que tu Karma sirva a tu JSON. Ejemplo:

     files = [ ... {pattern: 'json/**/*.json', included: false}, ... ] 
  3. Use la función readJSON en sus pruebas. Ejemplo:

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

He estado luchando por encontrar una solución para cargar datos externos en mis testcases. El enlace de arriba: http://dailyjs.com/2013/05/16/angularjs-5/ Funcionó para mí.

Algunas notas:

“defaultJSON” necesita ser utilizado como la clave en su archivo de datos falso, esto está bien, ya que solo puede referirse a JSON por defecto.

mockedDashboardJSON.js:

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

Luego en tu archivo de prueba:

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

Parece que tu solución es la correcta, pero hay dos cosas que no me gustan:

  • usa jasmine
  • requiere una nueva curva de aprendizaje

Acabo de toparme con este problema y tuve que resolverlo rápidamente ya que no me quedaba tiempo para la fecha límite, e hice lo siguiente

mi recurso json era enorme, y no pude copiarlo, pegarlo en la prueba, así que tuve que guardarlo como un archivo separado, pero decidí mantenerlo como javascript en lugar de json, y luego simplemente lo hice:

var someUniqueName = ... the json ...

y lo incluí en karma conf incluye ..

Todavía puedo simular una respuesta http de back-end si es necesario con ella.

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

También podría escribir un nuevo módulo angular para incluirlo aquí y luego cambiar el recurso json para que sea algo así como

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

y luego simplemente inyecte SomeUniqueName en la prueba, que se ve más limpio.

quizás incluso envolverlo en un servicio

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

esta solución fue más rápida para mí, igual de limpia y no requirió ninguna nueva curva de aprendizaje. así que prefiero este.

Estaba buscando lo mismo. Voy a probar este enfoque . Utiliza los archivos de configuración para incluir los archivos de datos falsos, pero los archivos son un poco más que json, porque el json debe pasarse al valor angular.module (‘MockDataModule’). Y luego las pruebas de su unidad también pueden cargar varios módulos y luego el conjunto de valores está disponible para ser inyectado en la llamada de inyección beforeEach.

También encontré otro enfoque que parece prometedor para las solicitudes xhr que no son costosas, es una gran publicación que describe las pruebas intermedias, que si entiendo bien permite que tu controlador / servicio realmente recupere datos como en una prueba e2e, pero tu prueba intermedia tiene real acceso al scope del controlador (e2e no lo creo).

Hay preprocesadores Karma que también funcionan con archivos JSON. Hay uno aquí:

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

Y el plug desvergonzado, este es uno que desarrollé que tiene soporte RequireJS

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

Puede usar el preprocesador karma-html2js para obtener los archivos json añadidos al __html__ global.

vea esta respuesta para más detalles: https://stackoverflow.com/a/22103160/439021

Aquí hay una alternativa a la respuesta de Cameron , sin la necesidad de jasmine-jquery ni ninguna configuración adicional de Karma, para probar, por ejemplo, un servicio angular que usa $resource :

 angular.module('myApp').factory('MyService', function ($resource) { var Service = $resource('/:user/resultset'); return { getResultSet: function (user) { return Service.get({user: user}).$promise; } }; }); 

Y la prueba de unidad correspondiente:

 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(); }); });