Здесь взаимодействуют две ловушки, ни одна из которых не имеет ничего общего с angular-google-maps.
Первая ловушка заключается в различии между услугами и поставщиками. В документации указано, что сервисы, фабрики, значения и константы являются частными случаями провайдеров. Для такого относительного новичка, как я, это, кажется, предполагает, что провайдеры и сервисы могут быть внедрены зависимостями где угодно одним и тем же способом. Однако верно и обратное: в любом месте, где могут быть внедрены зависимости, вы можете внедрить либо провайдеров, либо сервисы, но никогда и то, и другое.
Причина такого разделения заключается в строгом разделении времени настройки и времени выполнения (см. документацию модуля). Поставщики доступны во время настройки, а службы доступны во время выполнения. Время выполнения начинается после окончания времени настройки. Блоки .config
и .provider
выполняются во время настройки, в то время как большинство других типов блоков выполняются во время выполнения. Связь между определениями провайдера и службы проиллюстрирована в следующем фрагменте кода, адаптированном из провайдера. документация:
myModule.provider('myServiceProvider', ['injectedProvider', function MyServiceProvider(injectedProvider) {
// configuration time code depending on injectedProvider
this.$get = ["injectedService", function MyService(injectedService) {
// run time code depending on injectedService
}];
// more configuration time code
}]);
Как видите, служба определяется внутри поставщика. Поставщик определяется во время настройки (внешний блок, function MyServiceProvider
) и может зависеть от других поставщиков. Служба может быть извлечена из провайдера с помощью метода .$get
провайдера во время выполнения, как определено внутренним блоком (function MyService
), и может зависеть от других служб. Поставщик не может быть внедренной зависимостью службы или наоборот, но вы можете вложить определение службы в определение поставщика, как показано выше, чтобы он зависел от поставщиков косвенно. Когда вы определяете автономный сервис с помощью блока angular.module(...).service
, Angular за вашей спиной делает что-то вроде приведенного выше кода.
Другая ловушка заключается в том, что angular.mock.inject
, который является inject
из модульного теста в моем вопросе, может выполнять инъекции только во время выполнения. Для инъекций времени конфигурации вы должны делать реальную вещь, то есть инъекцию без имитации, создавая новый модуль с зависимостями времени конфигурации. Это то, на что намекал mguimard. Андре Эйфе опубликовал короткое руководство по как это сделать, которую я нашел по ссылке внизу ответа на мой другой вопрос.
В заключение, вот код, который решит проблему в моем вопросе:
'use strict';
describe('this spec', function() {
var gmapProvider;
beforeEach(function() {
angular.module('testAssist', ['uiGmapgoogle-maps'])
.config(function(uiGmapGoogleMapApiProvider) {
gmapProvider = uiGmapGoogleMapApiProvider;
});
module('testAssist'); // angular.mock.module
inject(); // angular.mock.inject
});
it('tries to configure uiGmapGoogleMapApiProvider', function() {
expect(gmapProvider.configure).toBeDefined();
});
});
Модуль 'testAssist'
в приспособлении (beforeEach
) существует с единственной целью — иметь зависимость времени конфигурации от uiGmapGoogleMapApiProvider
, поэтому я могу зафиксировать последний в локальной переменной gmapProvider
. Последующие вызовы module
и inject
являются бухгалтерскими уловками, чтобы гарантировать выполнение блока config
'testAssist'
. Благодаря захвату в тестовом примере (it
) не нужно делать инъекции, и я могу просто убедиться, что у провайдера есть метод configure
. Обратите внимание, что первый вызов angular.module
— это определение обычного модуля, а второй вызов module
— это специальная конструкция из фиктивной среды (angular.mock
).
Я отправил вышеуказанное решение в ветку fix1. на GitHub.
person
Julian
schedule
17.08.2016