2016-11-24 33 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()運行,但它運行正常並且測試通過。

這不是問題,我只是想了解它爲什麼運行,因爲我不明白觀察者如何射擊?是什麼導致它運行?

+1

'$ rootScope.dictionary = jsDictionary;'中的'jsDictionary'從哪裏來? – Jagrut

+0

通常,它將來自引導程序中的json文件,但出於測試目的,它是一個加載了測試文件的全局javascript對象。它很髒,但它在我學習解決我/我們構建我們的應用程序時遇到的其他錯誤時起作用。所有這些單元測試都在構建之後完成。我們正在學習這麼多,將來我們會採取TDD方法。 – Stuart

回答

2

在我看來,在全球範圍內初始化控制器是一個壞主意。這是因爲,在未來,當您想測試其他邏輯獨立的控制器時,您仍然會爲每個it()塊初始化每個控制器,我認爲沒有理由這麼做。

至於爲什麼你$watch被炒魷魚,你設置jsDictionary$rootScope和初始化它爲每個it()塊。在你的控制器代碼中,對於$watch,你只是檢查值是否存在,它將如你在前面的行中設置它,因此它調用init()塊。使用$手錶的正確的方法是:

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

做的是創建爲每個控制器一個describe()塊的一種更好的方式,把你的beforeEach()東西describe(),也是你的it()塊內,那些與該特定控制器相關。這也可以幫助您構建模塊化測試用例。

+0

我已經看到了像這樣設置的手錶,我也這麼做。字典監視器被設置爲檢查它是否存在,因爲我們在它被設置之前有它的使用中的種族問題,所以,我們這樣等待......但是,這已經被解決了,但是我需要的代碼基礎是在這個問題仍然存在的代碼的另一個分支上,因此我檢查它是否存在。我不認爲觀察者跑到'$ digest()'被調用了嗎?是'$ digest()'被自動調用的地方? – Stuart

+0

你能解釋一下在全球範圍內初始化控制器是什麼意思嗎?這個控制器被包裝在IIFE中,它不在$ rootScope上? – Stuart

+1

Angular有許多自動觸發'$ digest()'的內置函數。異步調用就是其中之一。在你的代碼中,'$ httpBackend.flush()'觸發摘要循環。 – Jagrut