Ich versuche ein Modul zu testen, das angular-google-maps
verwendet. Es schlägt fehl, weil angular.mock.inject
uiGmapGoogleMapApiProvider
nicht finden kann:
Ich kann nicht herausfinden, was falsch läuft. Hier ist der reduzierte Testfall:
%Vor%Das Ganze ist als ein lauffähiges Angular-Projekt von GitHub . Wenn Sie das Problem finden, antworten Sie bitte hier auf Stack Overflow. Bonuspunkte, wenn Sie auch eine Pull-Anfrage an das GitHub-Repository senden.
Hier spielen zwei Fallstricke eine Rolle, von denen keine etwas mit eckigen Google Maps zu tun hat.
Der erste Fehler liegt in der Unterscheidung zwischen Diensten und Anbietern. Die Dokumentation gibt an, dass Dienste, Fabriken, Werte und Konstanten Sonderfälle von Anbietern sind. Für einen relativen Anfänger wie mich scheint dies darauf hinzudeuten, dass Anbieter und Dienste überall auf die gleiche Art und Weise injiziert werden können. Das Gegenteil ist jedoch der Fall: An jeder Stelle, an der Abhängigkeiten injiziert werden können, können Sie entweder Anbieter oder Dienste injizieren, aber nie beides.
Der Grund für diese Kluft liegt in der strikten Trennung zwischen Konfigurationszeit und Laufzeit (siehe Moduldokumentation ). Anbieter sind während der Konfigurationszeit verfügbar, während Dienste während der Laufzeit verfügbar sind. Die Laufzeit beginnt nach dem Ende der Konfigurationszeit. Die Blöcke .config
und .provider
werden zur Konfigurationszeit ausgeführt, während die meisten anderen Blocktypen zur Laufzeit ausgeführt werden. Die Beziehung zwischen Provider- und Service-Definitionen wird im folgenden Codeschnipsel veranschaulicht, der aus der Provider-Dokumentation stammt:
Wie Sie sehen, ist ein Service innerhalb eines Providers definiert. Der Provider wird zur Konfigurationszeit definiert (äußerer Block, function MyServiceProvider
) und kann von anderen Anbietern abhängen. Der Dienst kann vom Anbieter mit der Methode .$get
des Providers zur Laufzeit extrahiert werden, wie im inneren Block ( function MyService
) definiert, und kann von anderen Diensten abhängen. Ein Provider kann keine injizierte Abhängigkeit eines Services sein oder umgekehrt, aber Sie können eine Servicedefinition innerhalb einer Providerdefinition wie oben beschrieben verschachteln, um sie von Providern indirekt abhängig zu machen. Wenn Sie einen "Standalone" -Dienst mit einem angular.module(...).service
-Block definieren, macht Angular etwas wie den obigen Code hinter Ihrem Rücken.
Der andere Nachteil ist, dass angular.mock.inject
, das ist die inject
aus dem Unit-Test in meiner Frage, kann nur Laufzeit-Injektionen tun. Für Konfigurationszeitinjektionen müssen Sie "die wirkliche Sache" machen, d. H. Nicht verspottete Injektion, indem Sie ein neues Modul mit Konfigurationszeitabhängigkeiten erstellen. Das ist was mguimard angedeutet hat. André Eife hat ein kurzes Tutorial veröffentlicht, in dem es darum geht, was zu tun ist Ich fand durch einen Link am Ende einer Antwort zu meiner anderen Frage.
Zusammenfassend ist hier der Code, der das Problem in meiner Frage beheben würde:
%Vor% Das 'testAssist'
Modul im Fixture ( beforeEach
) existiert nur zu dem Zweck, eine Konfigurationszeitabhängigkeit von uiGmapGoogleMapApiProvider
zu haben, also kann ich letztere in der lokalen Variable gmapProvider
erfassen. Die nachfolgenden Aufrufe von module
und inject
sind Buchhaltungstricks, um sicherzustellen, dass der config
-Block von 'testAssist'
ausgeführt wird. Dank des Captures muss innerhalb des Testfalls keine Injektion durchgeführt werden ( it
) und ich kann nur überprüfen, ob der Provider eine configure
-Methode hat. Beachten Sie, dass der erste angular.module
-Aufruf eine reguläre Moduldefinition ist, während der zweite module
-Aufruf ein spezielles Konstrukt aus dem Mocking-Framework ( angular.mock
) ist.
Ich habe die obige Lösung auf den Zweig fix1 auf GitHub.
Tags und Links javascript angularjs angular-mock karma-runner angular-providers