Unit test при загрузке приложений в приложении с помощью AngularJS
Мне нужно приложение для запуска некоторой конфигурации во время выполнения vi конечной точки HTTP.
Я написал простой сервис, чтобы сделать это:
module.factory('config', function ($http, analytics) {
return {
load: function () {
$http.get('/config').then(function (response) {
analytics.setAccount(response.googleAnalyticsAccount);
});
}
}
});
Затем я вызываю этот модуль в блоке выполнения моего модуля приложения:
angular.module('app').***.run(function(config) {
config.load();
});
Все работает хорошо, когда приложение работает, но в моих модульных тестах я получаю эту ошибку: "Ошибка: неожиданный запрос: GET/config"
Я знаю, что это значит, но я не знаю, как издеваться над ним, когда это происходит из блока выполнения.
Спасибо за помощь
ИЗМЕНИТЬ, чтобы добавить спецификацию
Вызов этого перед каждым
beforeEach(angular.mock.module('app'));
Попробовал это, чтобы высмеять $httpBackend:
beforeEach(inject(function($httpBackend) {
$httpBackend.expectGET('/config').respond(200, {'googleAnalyticsAccount':});
angular.mock.module('app')
$httpBackend.flush();
}));
Но получил:
TypeError: Cannot read property 'stack' of null
at workFn (/Users/arnaud/workspace/unishared-dredit/test/lib/angular/angular-mocks.js:1756:55)
TypeError: Cannot read property 'stack' of null
at workFn (/Users/arnaud/workspace/unishared-dredit/test/lib/angular/angular-mocks.js:1756:55)
TypeError: Cannot read property 'stack' of null
at workFn (/Users/arnaud/workspace/unishared-dredit/test/lib/angular/angular-mocks.js:1756:55)
EDIT с момента обновления до AngularJS 1.0.6
Поскольку я обновился до AngularJS 1.0.6, посоветовал Игорь из команды Angular, проблема исчезла, но теперь у меня есть этот, который звучит более "нормальным", но я все еще не могу выяснить, как это сделать.
Error: Injector already created, can not register a module!
Ответы
Ответ 1
Некоторое время я боролся с этой ошибкой, но мне удалось найти разумное решение.
То, что я хотел достичь, - это успешно заглушить Сервис и заставить ответ, на контроллерах можно было использовать $httpBackend
с заглушкой запроса или исключением перед запуском контроллера.
В app.run()
, когда вы загружаете module
, он инициализирует объект, а также связанные службы и т.д.
Мне удалось заглушить Сервис, используя следующий пример.
describe('Testing App Run', function () {
beforeEach(module('plunker', function ($provide) {
return $provide.decorator('config', function () {
return {
load: function () {
return {};
}
};
});
}));
var $rootScope;
beforeEach(inject(function (_$rootScope_) {
return $rootScope = _$rootScope_;
}));
it("defines a value I previously could not test", function () {
return expect($rootScope.value).toEqual('testing');
});
});
Я надеюсь, что это поможет вашему тестированию app.run()
в будущем.
Ответ 2
Я не знаю, продолжаете ли вы искать ответ на этот вопрос. Но вот некоторая информация, которая может помочь.
$injector - это одноэлемент для приложения, а не для модуля. Тем не менее, angular. Инжектор фактически попытается создать новый инжектор для каждого модуля (я полагаю, у вас есть
beforeEach(module("app"));
в начале.
У меня была такая же проблема при использовании Angular, RequireJS, Karma и Jasmine, и я выяснил два способа ее решения. Я создал поставщика для функции инжектора в качестве отдельной зависимости в моих тестах. Например, MyInjectorProvider, который предоставляет один экземпляр $инжектора.
Другим способом было перемещение следующих утверждений:
beforeEach(module("app"));
beforeEach(inject(function($injector){
...
})
внутри описания тестового набора. Итак, вот как это выглядело раньше:
define(['services/SignupFormValidator'], function(validator){
var validator;
beforeEach(module("app"));
beforeEach(inject(function($injector){
validator = $injector.get("SignupFormValidator");
})
describe("Signup Validation Tests", function(){
it("...", function(){...});
});
});
После применения исправления это выглядит так:
define(['services/SignupFormValidator'], function(validator){
var validator;
describe("Signup Validation Tests", function(){
beforeEach(module("app"));
beforeEach(inject(function($injector){
validator = $injector.get("SignupFormValidator");
});
it("...", function(){...});
});
});
Оба решения работали в моем случае.
Ответ 3
Вы должны издеваться над каждым запросом HTTP ngMock. $httpBackend. Кроме того, вот руководство.
Обновление
Вам не нужна вещь angular.mock.module
, просто нужно ввести свой модуль приложения. Что-то вроде этого:
var httpBackend;
beforeEach(module('app'));
beforeEach(inject(function($httpBackend) {
httpBackend = $httpBackend;
$httpBackend.expectGET('/config').respond(200, {'googleAnalyticsAccount': 'something'});
}));
В ваших тестах, когда вам нужен издеваемый http для ответа, вы вызываете httpBackend.flush()
. Вот почему мы ссылаемся на него, поэтому вам не нужно вводить его в каждый отдельный тест, который у вас есть.
Обратите внимание, что вам нужно будет загрузить angular -mock.js, чтобы он работал.