web-dev-qa-db-ja.com

Angularユニットテストにサービスを注入する際に不明なプロバイダーエラーを取得する

私はAngularにかなり慣れており、Stack Overflowで同様に関連する質問をすべて確認しましたが、何も助けてくれませんでした。ユニットテストにサービスを挿入しようとするとエラーが発生します。コードを下に示しました-誰かが明らかなエラーを見つけられることを願っています。

次のように、モジュールを個別の。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
}]);

これが私の単体テストです-単体テストの実行時にエラーを引き起こすEventingServiceを挿入しようとする行:

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テストのヘルプはゴミですので、私は現在困惑しています-誰でもできるヘルプや提案は非常に感謝されます。ありがとう。

30
Dud

私はこれに遭遇し、$ injectorを明示的に使用してサービスを取得するように切り替えることで解決しました:

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

これがなぜ機能するのか、なぜシンプルなのか

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

ありませんが、内部を調査する時間はありません。常に1つのコーディングスタイルを使用し、それに従うことをお勧めします。

このスタイルは、テストで使用する変数の名前がサービスの正しい名前であるという点で優れています。しかし、それは少し冗長です。

別のangular $ rootScopeのような奇妙な変数名を使用するマジック機能がありますが、そのハックな外観は好きではありません。

ほとんどの場合、モジュールが含まれていないため、このエラーが発生します。

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

コントローラー(dashboard.controllersモジュール)は、異なるモジュール(dashboard.services)モジュール署名の依存関係モジュールを参照する必要がある場合:

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

この質問はかなり古いですが、私はこれに似た問題を解決するのにかなりの時間を失いました、すなわち:

Error: Unknown provider: SomeServiceProvider <- SomeService

したがって、私はこの問題の別の考えられる原因をここに残しています。うまくいけば、誰かに役立つでしょう。

私の場合、私のプロジェクトにはまったく同じ名前の2つのモジュールがありましたが、異なる依存関係が作成されています。つまり、次の2つの異なる.jsファイルがあります:

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

From angular documentation:

1つの引数を渡すと、既存のangle.Moduleが取得されますが、複数の引数を渡すと、新しいangle.Moduleが作成されます

結論:テストで注入されたのは、誤った依存関係を持つモジュールであったことが判明しました。誤って作成されていたモジュールから2番目の引数を削除すると、問題は解決しました。

2
Emanuel Miranda

他の集約モジュールに依存する追加モジュールを次のように定義しようとしましたか?

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

したがって、beforeEachで、次のように両方のサブモジュールが定義されている1つのモジュールを指定できます。

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);
    });
});
0
user2562481