2016-11-24 15 views
0

これは私のコントローラです。

(function() { 
    'use strict'; 

    app.controller('NavController', navController); 

    function navController($rootScope, $scope, $location, $window, NavFactory) { 

     $scope.menuConfig = null; 
     $scope.menuItems = []; 
     $scope.isActive = isActive; 
     $scope.toggleBurgerMenu = toggleBurgerMenu; 
     $scope.toggleDeviceSettings = toggleDeviceSettings; 

     $rootScope.$watch('dictionary', function(dictionary) { 
      if (dictionary) { 
       init(); 
      } 
     }); 

     function init() { 
      $scope.menuConfig = $rootScope.config.navigation; 
      NavFactory.GetMenuItems().then(onGetMenuItems, $scope.onAPIError); 
     } 

     function onGetMenuItems(response) { 
      $scope.moduleConfig = response.moduleConfig; 
      $scope.menuItems = response.menuItems; 
     } 
    } 
})(); 

これは私のテストスイート(カルマ、ジャスミン) です( 'からNavController機能'、機能(){

var $rootScope, $scope, $location, $window, $controller, createController, NavFactory, CacheFactory, toastr; 

beforeEach(module('mockedDashboard')); 

beforeEach(inject(function(_$rootScope_, _$controller_, _$location_, _$window_, _NavFactory_, _toastr_) { 
    $location = _$location_; 
    $window = _$window_; 
    toastr = _toastr_; 

    $rootScope = _$rootScope_; 
    $rootScope.dictionary = jsDictionary; 
    $rootScope.config = jsConfig; 
    $rootScope.config.contentFolder = '_default'; 

    $scope = _$rootScope_.$new(); 
    $scope.burgerMenuActive = false; 
    //mock the parent controller function 
    $scope.navigate = function(path) { 
     $location.path('/' + path); 
    }; 
    // end mock 

    createController = function() { 
     return _$controller_('NavController', { 
      '$scope': $scope 
     }); 
    }; 
    $controller = createController(); 
})); 

// We are using CacheFactory in this project, when running multiple tests on the controller 
// we need to destroy the cache for each test as the controller is initialized for each test. 
afterEach(inject(function(_CacheFactory_) { 
    CacheFactory = _CacheFactory_; 
    CacheFactory.destroy('defaultCache'); 
})); 

describe('init()', function() { 

    it('should call NavFactory.GetMenuItems and set moduleConfig and menuItems on $scope', inject(function(_$httpBackend_) { 

     var $httpBackend = _$httpBackend_; 

     expect($scope.moduleConfig).toBe(undefined); 
     expect($scope.menuItems.length).toBe(0); 

     var responseData = [{ 
      "path": "stats", 
      "url": "./app/modules/dashboard/modules/score/score.index.html", 
      "icon": "fa fa-fw fa-pie-chart", 
      "dashboardEnabled": true, 
      "burgerMenu": true, 
      "barMenu": false, 
      "barMenuOrder": -1, 
      "bottomMenu": true, 
      "bottomMenuOrder": 3, 
      "order_sm": 1, 
      "order_md": 2, 
      "order_lg": 2 
     }]; 

     $httpBackend.expectGET('../content/_default/config/modules.json').respond(responseData); 
     $httpBackend.flush(); 

     expect($scope.moduleConfig).not.toBe(undefined); 
     expect($scope.menuItems.length > 0).toBe(true); 
    })); 
});}); 

私は$スコープを実行する必要があることを期待して説明します。$ダイジェスト( )ウォッチャーを起動してinit()を実行させるには、init()を実行しますが、そのまま実行され、テストは成功します。

これは問題ではありません。ウォッチャーがどのように発砲しているのか理解できないのですが、何が起こるのですか?

+1

'$ rootScope.dictionary = jsDictionary;の' jsDictionary'はどこから来ますか? – Jagrut

+0

通常、ブートストラップのjsonファイルから来ますが、テスト目的のために、テストファイルをロードしたグローバルなjavascriptオブジェクトです。それは汚いですが、私は私/私たちのアプリを作った他の間違いを解決することを学んでいる間に動作します。すべてのユニットテストはビルド後に行われます。私たちはあまりにも多くのことを学んでおり、将来私たちはTDDアプローチを取っていきます。 – Stuart

答えて

2

私の意見では、コントローラをグローバルスコープで初期化することは悪い考えです。これは、将来的に、論理的に独立した他のコントローラをテストしたい場合、ブロックするたびに各コントローラを初期化することになります。理由はわかりません。あなたの$watchがトリガーされますなぜ、あなたは$rootScopejsDictionaryを設定し、各it()ブロックのためにそれを初期化するためとして

。あなたのコントローラコードでは、$watchについては、値が存在するかどうかをチェックしています。値が存在するかどうかは、前の行で設定した通りであるため、ブロックinit()が呼び出されます。 $の時計を使用しての正しい方法は次のようになります。

$rootScope.$watch('dictionary', function(oldVal, newVal){ 
}); 

行うためのより良い方法は、各コントローラのdescribe()ブロックを作成describe()の内側にあなたのbeforeEach()のものを入れても、あなたのit()ブロック、あるものことであろうその特定のコントローラに関連する。これはモジュール化されたテストケースを構築するのにも役立ちます。

+0

私はこのような時計を見てきました。私もそうしています。ディクショナリーウォッチは、それが設定される前にレースの問題があるのでチェックするように設定されているので、このように待っています...しかし、これは解決されましたが、私が作業する必要があるコードベースはこの問題がまだ存在するコードの別のブランチ上にあるので、その存在を確認します。私は$ digest()が呼び出されるまでウォッチャーが走ったとは思わなかった? '$ digest()'は自動的にどこかで呼び出されますか? – Stuart

+0

コントローラをグローバルスコープで初期化することによって何を意味するのか説明してください。このコントローラーはIIFEで包まれ、$ rootScopeにはありませんか? – Stuart

+1

Angularには '$ digest()'を自動的に起動する組み込み関数が多数あります。非同期呼び出しはその1つです。あなたのコードでは、 '$ httpBackend.flush()'がダイジェストサイクルをトリガします。 – Jagrut

関連する問題