Tengo una aplicación AngularJS configurada con pruebas usando 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 resto de la aplicación y devuelve ese objeto convertido. Eso es.
Para mis pruebas, me gustaría que tuviera archivos JSON separados (* .json) con contenido JSON simulado únicamente, 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 incrustar 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 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 recibí:
Error: Unexpected request: GET mock-data/two-metrics-with-anomalies.json
Lo que, según tengo entendido, significa que espera una respuesta simulada de $ httpBackend. Entonces ... en este punto no sabía cómo cargar el archivo usando las utilidades de Angular, así que pensé en probar jQuery para ver si al menos podía hacer que eso funcionara:
$.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 resto de los archivos que he configurado para ser "incluidos" por Karma se solicitan en, por ejemplo:
/base/src/app.js
Aparentemente, Karma está configurando una especie de directorio base desde el que servir los archivos. Así que, por diversión, cambié mi solicitud de datos jquery a
$.getJSON('base/mock-data/two-metrics-with-anomalies.json')...
¡Y funciona! Pero ahora me siento sucia y necesito darme una ducha. Ayúdame a sentirme limpio de nuevo.
fuente
Servir JSON a través del dispositivo es lo más fácil, pero debido a nuestra configuración no pudimos hacerlo fácilmente, así que escribí una función auxiliar alternativa:
Repositorio
Instalar en pc
$ bower install karma-read-json --save OR $ npm install karma-read-json --save-dev OR $ yarn add karma-read-json --dev
Uso
Coloque karma-read-json.js en sus archivos de Karma. Ejemplo:
files = [ ... 'bower_components/karma-read-json/karma-read-json.js', ... ]
Asegúrese de que su JSON esté siendo servido por Karma. Ejemplo:
files = [ ... {pattern: 'json/**/*.json', included: false}, ... ]
Utilice la
readJSON
función en sus pruebas. Ejemplo:var valid_respond = readJSON('json/foobar.json'); $httpBackend.whenGET(/.*/).respond(valid_respond);
fuente
npm install karma-read-json
lugar debower install karma-read-json
He estado luchando por encontrar una solución para cargar datos externos en mis casos de prueba. El enlace anterior: http://dailyjs.com/2013/05/16/angularjs-5/ Funcionó para mí.
Algunas notas:
"defaultJSON" debe usarse como la clave en su archivo de datos simulado, esto está bien, ya que puede referirse a defaultJSON.
mockedDashboardJSON.js:
'use strict' angular.module('mockedDashboardJSON',[]) .value('defaultJSON',{ fakeData1:{'really':'fake2'}, fakeData2:{'history':'faked'} });
Luego, en su 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 .... }
fuente
Parece que tu solución es la correcta, pero hay 2 cosas que no me gustan:
Acabo de encontrarme 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 y pegarlo en la prueba, así que tuve que mantenerlo en un archivo separado, pero decidí mantenerlo como javascript en lugar de json, y luego simplemente lo hice:
var someUniqueName = ... the json ...
e incluí esto en karma conf incluye ...
Todavía puedo burlarme de una respuesta http backend si es necesario.
$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 como
angular.module('hugeJsonResource', []).constant('SomeUniqueName', ... the json ... );
y luego simplemente inyecte
SomeUniqueName
en la prueba, que se ve más limpia.tal vez 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.
fuente
Yo buscaba lo mismo. Voy a probar este enfoque . Utiliza los archivos de configuración para incluir los archivos de datos simulados, pero los archivos son un poco más que json, porque el json debe pasarse al valor angular.module ('MockDataModule'). Y luego sus pruebas unitarias también pueden cargar varios módulos y luego el conjunto de valores está disponible para inyectarse 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 excelente publicación que describe las pruebas intermedias, que si entiendo bien, permite que su controlador / servicio recupere datos como en una prueba e2e, pero su prueba intermedia tiene datos reales acceso al alcance del controlador (e2e no creo).
fuente
Hay preprocesadores de Karma que también funcionan con archivos JSON. Hay uno aquí:
https://www.npmjs.org/package/karma-ng-json2js-preprocessor
Y enchufe desvergonzado, este es uno que desarrollé y que tiene soporte RequireJS
https://www.npmjs.org/package/karma-ng-json2js-preprocessor-requirejs
fuente
Puede usar el preprocesador karma-html2js-preprocessor para agregar los archivos json al __html__ global.
consulte esta respuesta para obtener más detalles: https://stackoverflow.com/a/22103160/439021
fuente
Aquí hay una alternativa a la respuesta de Cameron , sin la necesidad de
jasmine-jquery
ninguna configuración adicional de Karma, para probar, por ejemplo, un servicio Angular usando$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 unitaria 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(); }); });
fuente