web-dev-qa-db-ja.com

ユニットテストの依存性注入

私はジャスミンとカルマに真新しいです。環境が適切にセットアップされ、非常に基本的な単体テストを実行できると思いますが、コントローラーをインスタンス化しようとすると、不明なプロバイダーエラーが発生し、これをデバッグする方法がわかりません。 stateProviderの依存関係を渡す必要がありますか?角のある種の例ではこれは見られません。

Bower.json:

{
"name": "starter",
  "description": "A starter project for AngularJS",
  "version": "2.0.0",
  "homepage": "https://starter.com",
  "private": true,
  "dependencies": {
      "angular": "1.2.x",
      "angular-route": "1.2.x",
      "angular-loader": "1.2.x",
      "angular-mocks": "~1.2.15"
  }
}

ホームコントローラー:

angular.module('home').controller('Home', function($scope, $rootScope, $state) {

    console.log($scope.pageType);

    $rootScope.pageType = 'home';

    /*
     * Takes in a state and transitions the app to that state.
     */
    $scope.goTo = function(value) {
        $state.transitionTo(value);
    }

    /*
     * Handles what happens after clicking log-in
     */
    $scope.loginClicked = function() {
        $state.transitionTo('log-in');
    }
});

テストファイル:

'use strict';

/* jasmine specs for controllers go here */

describe('Home', function() {
    beforeEach(module('home'));

    it('should run tests', inject(function() {
        expect(null).toBeDefined();
    }));

    it('should not say true equals false', function() {
        expect(false).not.toBe(true);
    });

    it('should say true equals true', function() {
        expect(true).toBe(true);
    });

    it('should say false does not equal true', function() {
        expect(false).not.toBe(true);
    });

    it('should create "phones" model with 3 phones', inject(function($controller,$rootScope) {

    /*
     * 
     * COMMENTING OUT THESE LINES = PASS
     *
     */
        var scope = $rootScope.$new(),
            ctrl = $controller('Home', {$scope:scope});
        expect(ctrl).not.toBe(null);
    }));

});

エラー:

    Error: [$injector:unpr] Unknown provider: $stateProvider <- $state
http://errors.angularjs.org/1.2.16/$injector/unpr?p0=%24stateProvider%20%3C-%20%24state
    at /Users/jlett/bower_components/angular/angular.js:78:12
    at /Users/jlett/bower_components/angular/angular.js:3705:19
    at Object.getService [as get] (/Users/jlett/bower_components/angular/angular.js:3832:39)
    at /Users/jlett/bower_components/angular/angular.js:3710:45
    at getService (/Users/jlett/bower_components/angular/angular.js:3832:39)
    at invoke (/Users/jlett/bower_components/angular/angular.js:3859:13)
    at Object.instantiate (/Users/jlett/bower_components/angular/angular.js:3880:23)
    at /Users/jlett/bower_components/angular/angular.js:7134:28
    at null.<anonymous> (/Users/jlett/test/unit/home-controller_tests.js:26:20)
    at Object.invoke (/Users/jlett/bower_components/angular/angular.js:3869:17)
Error: Declaration Location
    at window.inject.angular.mock.inject (/Users/jlett/bower_components/angular-mocks/angular-mocks.js:2132:25)
    at null.<anonymous> (/Users/jlett/test/unit/home-controller_tests.js:24:54)
    at /Users/jlett/zoetis-rimadyl-mobile/test/unit/home-controller_tests.js:5:1
12
jeffctown

注射剤モジュールの1つが含まれていない場合、このエラーが発生します。

たとえば、あなたは

beforeEach(module('home'));

$state依存関係がhomeモジュールにない場合は、そのモジュールも含める必要があります。私は$stateに精通していません(angular-uiのルーターだと思いますか?angular.jsサービスのみが$で始まることになっています)。 angular uiの場合、次のように設定する必要があります。

beforeEach(module('ui.router'));
beforeEach(module('home'));

このようにして、angularのテストランナーは、テストを実行するために必要なモジュールを認識します。

実際、homeモジュールを含めると、そのモジュールの依存関係としてui.router依存関係が定義されている限り、これを行うことができます。これが正しく構成されている場合は、テストに含まれているファイルの順序を確認する必要がある場合があります。たとえば、ui-routerファイルがテストに含まれていること、およびkarmaの構成のhomeモジュールの前に参照されていることを確認します。

36
Jim Schubert

コントローラーに$state依存関係を含めるため、コントローラーの単体テストで$stateを指定する必要があります。

    var $scope = $rootScope.$new(),
    ctrl = $controller('Home', {
               $scope: $scope,
               $state: {} //Or inject the state using the injector service and then you can use some jasmine spies to mock the function calls or just to spy on 'em.
          });
    expect(ctrl).not.toBe(null);

あなたのそれは変更でブロックします...

it('should create "phones" model with 3 phones', inject(function($controller, $rootScope, $state) {

    /*
     * 
     * COMMENTING OUT THESE LINES = PASS
     *
     */
        var scope = $rootScope.$new(),
            ctrl = $controller('Home', {$scope:scope, $state: $state});
        expect(ctrl).not.toBe(null);
    }));

ただし、単体テストのセットアップでは、このセットアップで説明するように、コントローラーセットアップ用の関数を作成するのが好きです ここ

8
Sten Muchow