Загрузка mock файла JSON в рамках теста Karma + AngularJS
У меня есть приложение AngularJS, настроенное с помощью тестов с использованием Karma + Jasmine. У меня есть функция, которую я хочу проверить, которая принимает большой объект JSON, преобразует его в формат, который больше потребляется остальной частью приложения, и возвращает этот преобразованный объект. Что это.
Для моих тестов, я бы хотел, чтобы у вас были отдельные файлы JSON (*.json) только с содержимым только mock JSON - no script. Для теста я хотел бы загрузить файл JSON и передать объект в функцию, которую я тестирую.
Я знаю, что могу встроить JSON в mock factory, как описано здесь: http://dailyjs.com/2013/05/16/angularjs-5/, но я действительно хочу, чтобы JSON не содержаться в script - только прямые файлы JSON.
Я пробовал несколько вещей, но в этой области я довольно неплохо. Во-первых, я настроил свою Карму, чтобы включить мой JSON файл, чтобы посмотреть, что он будет делать:
files = [
...
'mock-data/**/*.json'
...
]
В результате получилось:
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
Итак, я изменил его, чтобы просто обслуживать файлы, а не "включать" их:
files = [
...
{ pattern: 'mock-data/**/*.json', included: false }
...
]
Теперь, когда они только обслуживаются, я решил попробовать загрузить файл, используя $http из моей спецификации:
$http('mock-data/two-metrics-with-anomalies.json')
Когда я запустил спецификацию, которую я получил:
Error: Unexpected request: GET mock-data/two-metrics-with-anomalies.json
Что в моем понимании означает, что он ожидает издевательский ответ от $httpBackend. Итак... на данный момент я не знал, как загрузить файл с помощью утилиты Angular, поэтому я подумал, что попробую jQuery, чтобы узнать, могу ли я хотя бы заставить это работать:
$.getJSON('mock-data/two-metrics-with-anomalies.json').done(function(data) {
console.log(data);
}).fail(function(response) {
console.log(response);
});
Это приводит к:
Chrome 27.0 (Mac) LOG: { readyState: 4,
responseText: 'NOT FOUND',
status: 404,
statusText: 'Not Found' }
Я проверяю этот запрос в Чарльзе, и он делает запрос на
/mock-data/two-metrics-with-anomalies.json
В то время как остальные файлы, которые я настроил для включения в Karma, запрашиваются, например:
/base/src/app.js
По-видимому, Karma настраивает какой-то базовый каталог для работы с файлами. Итак, для ударов я изменил запрос данных jquery на
$.getJSON('base/mock-data/two-metrics-with-anomalies.json')...
И это работает! Но теперь я чувствую себя грязным и должен принять душ. Помогите мне снова почувствовать себя чистым.
Ответы
Ответ 1
Я использую установку angular с семенем angular. Я закончил тем, что решил это с помощью прямых файлов .json fixture и jasmine-jquery.js. Другие ссылались на этот ответ, но мне потребовалось некоторое время, чтобы собрать все фигуры в нужном месте. Надеюсь, это поможет кому-то другому.
У меня есть мои json файлы в папке /test/mock
, а мой webapp находится в /app
.
my karma.conf.js
содержит эти записи (среди прочих):
basePath: '../',
files: [
...
'test/vendor/jasmine-jquery.js',
'test/unit/**/*.js',
// fixtures
{pattern: 'test/mock/*.json', watched: true, served: true, included: false}
],
тогда мой тестовый файл:
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);
});
});
Реальным трюком был jasmine.getJSONFixtures().fixturesPath='base/test/mock';
Я первоначально установил его только test/mock
, но ему понадобился base
.
Без базы я получил такие ошибки:
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
Ответ 2
Обслуживание JSON через прибор является самым простым, но из-за нашей настройки мы не могли бы так легко сделать, поэтому я написал альтернативную вспомогательную функцию:
Установка
$ bower install karma-read-json --save
OR
$ npm install karma-read-json --save-dev
OR
$ yarn add karma-read-json --dev
Использование
-
Поместите karma-read-json.js в свои файлы Karma. Пример:
files = [
...
'bower_components/karma-read-json/karma-read-json.js',
...
]
-
Убедитесь, что ваш JSON обслуживается кармой. Пример:
files = [
...
{pattern: 'json/**/*.json', included: false},
...
]
-
Используйте функцию readJSON
в своих тестах. Пример:
var valid_respond = readJSON('json/foobar.json');
$httpBackend.whenGET(/.*/).respond(valid_respond);
Ответ 3
Я пытаюсь найти решение для загрузки внешних данных в свои тестовые файлы.
Вышеуказанная ссылка: http://dailyjs.com/2013/05/16/angularjs-5/
Работал для меня.
Некоторые примечания:
"defaultJSON" необходимо использовать в качестве ключа в вашем файле данных mock, это прекрасно, поскольку вы можете просто ссылаться на defaultJSON.
mockedDashboardJSON.js:
'use strict'
angular.module('mockedDashboardJSON',[])
.value('defaultJSON',{
fakeData1:{'really':'fake2'},
fakeData2:{'history':'faked'}
});
Затем в тестовом файле:
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
....
}
Ответ 4
похоже, что ваше решение является правильным, но есть две вещи, которые мне не нравятся:
- использует жасмин
- для этого требуется новая кривая обучения
Я просто столкнулся с этой проблемой и должен был быстро ее решить, так как у меня не было времени на крайний срок, и я сделал следующее
Мой ресурс json был огромным, и я не мог скопировать его в тест, поэтому мне пришлось оставить его отдельным файлом, но я решил сохранить его как javascript, а не json, а затем просто:
var someUniqueName = ... the json ...
и я включил это в karma conf.
Я все еще могу высмеять HTTP-запрос бэкэнда, если это необходимо.
$httpBackend.whenGET('/some/path').respond(someUniqueName);
я также мог бы написать новый модуль angular, который будет включен здесь, а затем изменить ресурс json, чтобы быть чем-то вроде
angular.module('hugeJsonResource', []).constant('SomeUniqueName', ... the json ... );
а затем просто введите SomeUniqueName
в тест, который выглядит более чистым.
возможно даже обернуть его в службу
angular.module('allTestResources',[]).service('AllTestResources', function AllTestResources( SomeUniqueName , SomeOtherUniqueName, ... ){
this.resource1 = SomeUniqueName;
this.resource2 = SomeOtherUniqueName;
})
эти решения были быстрее для меня, так же чисты и не требовали новой кривой обучения. поэтому я предпочитаю этот.
Ответ 5
Я искал то же самое. Я собираюсь попробовать этот подход. Он использует файлы конфигурации для включения файлов данных mock, но файлы немного больше, чем json, потому что json нужно передать в значение angular.module('MockDataModule'). Затем ваши модульные тесты также могут загружать несколько модулей, а затем набор значений доступен для инжекции в вызов beforeEach для инъекций.
Также найдено другой подход, который выглядит многообещающим для запросов xhr, которые не являются дорогостоящими, это отличная статья, которая описывает промежуточное тестирование, которое, если я понять право позволяет вашему контроллеру/службе фактически получать данные, как в тесте e2e, но ваш средний тест имеет фактический доступ к области управления (e2e, я не думаю).
Ответ 6
Вы можете использовать karma-html2js-preprocessor, чтобы получить json файлы, добавленные в глобальный __html__.
см. этот ответ для деталей: fooobar.com/questions/69240/...
Ответ 7
Существуют препроцессоры Karma, которые также работают с файлами JSON. Здесь есть один из них:
https://www.npmjs.org/package/karma-ng-json2js-preprocessor
И бесстыдный плагин, это тот, который я разработал с поддержкой RequireJS
https://www.npmjs.org/package/karma-ng-json2js-preprocessor-requirejs
Ответ 8
Ниже приведена альтернатива Cameron, без необходимости в jasmine-jquery
и никакой дополнительной конфигурации Karma, чтобы проверить, например. службы Angular, используя $resource
:
angular.module('myApp').factory('MyService', function ($resource) {
var Service = $resource('/:user/resultset');
return {
getResultSet: function (user) {
return Service.get({user: user}).$promise;
}
};
});
И соответствующий unit test:
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();
});
});