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

Ошибка получения неизвестного поставщика при вводе службы в Angular unit test

Я новичок в Angular и просмотрел все похожие вопросы о переполнении стека, но ни один из них не помог мне. Я считаю, что все правильно настроено, но при попытке ввести службу в unit test я все равно получаю ошибку "Неизвестный поставщик". Я изложил свой код ниже - надеюсь, кто-то может заметить очевидную ошибку!

Я определяю свои модули в отдельном файле .js следующим образом:

angular.module('dashboard.services', []);
angular.module('dashboard.controllers', []);

Здесь я определяю службу под названием EventingService (с логикой, удаленной для краткости):

angular.module('dashboard.services').factory('EventingService', [function () {
    //Service logic here
}]);

Вот мой контроллер, который использует EventingService (все это отлично работает во время выполнения):

angular.module('dashboard.controllers')
    .controller('Browse', ['$scope', 'EventingService', function ($scope, eventing) {
        //Controller logic here
}]);

Вот мой unit test - это строка, в которой я пытаюсь внедрить EventingService, которая вызывает ошибку при запуске unit test:

describe('Browse Controller Tests.', function () {
    beforeEach(function () {
        module('dashboard.services');
        module('dashboard.controllers');
    });

    var controller, scope, eventingService;

    beforeEach(inject(function ($controller, $rootScope, EventingService) {
        scope = $rootScope.$new();
        eventingService = EventingService

        controller = $controller('Browse', {
            $scope: scope,
            eventing: eventingService
        });
    }));


    it('Expect True to be True', function () {
        expect(true).toBe(true);
    });
});

Когда я запускаю тест, я получаю эту ошибку:

Ошибка: Неизвестный поставщик: EventingServiceProvider < - EventingService

Я убедился, что в моем файле jasmine specrunner.html есть все необходимые исходные файлы (это проект Asp.Net MVC):

<!-- Include source files here... -->
@Scripts.Render("~/bundles/jquery")
<script type="text/javascript" src="@Url.Content("~/Scripts/angular.js")"></script>  
<script type="text/javascript" src="@Url.Content("~/Scripts/angular-mocks.js")"></script>                 

<script type="text/javascript" src="@Url.Content("~/App/scripts/app.js")"></script>                       <!-- Angular modules defined in here -->
<script type="text/javascript" src="@Url.Content("~/App/scripts/services/eventing.js")"></script>         <!-- My Eventing service defined here -->


<script type="text/javascript" src="@Url.Content("~/App/scripts/controllers/browse.js")"></script>        <!-- My Browse controller defined here -->

<!-- Include spec files here... -->
<script type="text/javascript" src="@Url.Content("~/App/tests/browse.js")"></script>                      <!-- The actual unit test here -->

Я просто не могу понять, почему Angular бросает эту ошибку с жалобами на мой EventingService. Мой контроллер отлично работает во время выполнения - это просто, когда я пытаюсь проверить его, что я получаю сообщение об ошибке, поэтому мне любопытно, что я что-то придумал с насмешкой/инъекцией.

Помощь по тестированию Angular - это мусор, поэтому я сейчас в тупике - любая помощь или предложения, которые кто-либо может дать, будут очень оценены. Спасибо.

4b9b3361

Ответ 1

Я просто столкнулся с этим и решил его, переключившись на получение сервиса с помощью форварда $явно:

var EventingService, $rootScope;
beforeEach(inject(function($injector) {
  EventingService = $injector.get('EventingService');
  $rootScope = $injector.get('$rootScope');
}));

Хотел бы я рассказать вам, почему это работает и почему простой

beforeEach(inject(function(EventingService) {   ....  }));

нет, но у меня нет времени, чтобы исследовать внутренности. Всегда лучше использовать один стиль кодирования и придерживаться его.

Этот стиль лучше в том, что имя переменной, которое вы используете в своих тестах, является правильным именем службы. Но это немного многословно.

Существует еще одна волшебная функция angular, которая использует имена странных переменных, такие как $rootScope, но мне не нравится хакерский вид этого.

Обратите внимание, что большую часть времени люди получают эту ошибку, потому что они не включают модули:

beforeEach(module('capsuling'));
beforeEach(module('capsuling.capsules.services'));

Ответ 2

Если ваши контроллеры (определенные в модуле dashboard.controllers) зависят от некоторых служб, которые заключены в другой модуль (dashboard.services), вам нужно ссылаться на модули зависимостей в вашей сигнатуре модуля:

angular.module('dashboard.services', []);
angular.module('dashboard.controllers', ['dashboard.services']);

Ответ 3

Пока этот вопрос довольно старый, я потерял значительное время, решая проблему, подобную этой, т.е.:

Error: Unknown provider: SomeServiceProvider <- SomeService

Следовательно, я оставляю здесь еще одну возможную причину этой проблемы. Надеюсь, это кому-то помогло.

В моем случае у меня в моем проекте были два модуля с точно таким же именем, но с разными зависимостями, создаваемыми, то есть два разных файла .js с:

angular.module('moduleName', [dependencies]))

Из angular документации:

Передача одного аргумента извлекает существующий angular.Module, тогда как передача нескольких аргументов создает новый angular.Module

Заключение. Оказывается, что то, что вводилось в тест, было модулем с неправильными зависимостями. Удаление второго аргумента из модуля, который был ошибочно создан, решает проблему.

Ответ 4

Вы пробовали определить дополнительный модуль, который зависит от ваших других агрегированных модулей следующим образом:

angular.module( 'dashboard', [ 'dashboard.services', 'dashboard.controllers' ] )

Итак, вы можете в beforeEach указать один модуль, который имеет оба подмодуля, определенные в нем так:

describe('Browse Controller Tests.', function () {
    beforeEach(function () {
        module('dashboard');
    });

    var controller, scope, eventingService;

    beforeEach(inject(function ($controller, $rootScope, EventingService) {
        scope = $rootScope.$new();
        eventingService = EventingService

        controller = $controller('Browse', {
            $scope: scope,
            eventing: eventingService
        });
    }));


    it('Expect True to be True', function () {
        expect(true).toBe(true);
    });
});