Подтвердить что ты не робот

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!
4b9b3361

Ответ 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, чтобы он работал.