2014-12-04 89 views
4

的情況是我有一個ChildCtrl控制器從BaseCtrl繼承以下this inheritance pattern

angular.module('my-module', []) 
    .controller('BaseCtrl', function ($scope, frobnicate) { 
     console.log('BaseCtrl instantiated'); 

     $scope.foo = frobnicate(); 

     // do a bunch of stuff 
    }) 

    .controller('ChildCtrl', function ($controller, $scope) { 
     $controller('BaseCtrl', { 
      $scope: $scope, 
      frobnicate: function() { 
       return 123; 
      } 
     }); 
    }); 

假設BaseCtrl做了一堆東西,已經是很好的測試,我想測試ChildCtrl與某些參數實例化BaseCtrl。我最初的想法是這些方針的東西:

describe("ChildCtrl", function() { 
    var BaseCtrl; 

    beforeEach(module('my-module')); 

    beforeEach(module(function($provide) { 
     BaseCtrl = jasmine.createSpy(); 
     $provide.value('BaseCtrl', BaseCtrl); 
    })); 

    it("inherits from BaseCtrl", inject(function ($controller, $rootScope) { 
     $controller('ChildCtrl', { $scope: $rootScope.$new() }); 

     expect(BaseCtrl).toHaveBeenCalled(); 
    })); 
}); 

然而,當我運行測試的諜照,不會被調用控制檯顯示「BaseCtrl實例化」,表明我的實例是$controller使用的實際控制人,而不是提供$provide.value()

什麼是最好的測試方法?

回答

5

因此,看起來$controller不會按$provide.value()名稱空間中的名稱搜索控制器。相反,您必須使用$controllerProvider.register()方法,該方法只能從module.config()塊訪問。幸運的是,我們可以使用一個鉤子來訪問被測模塊上的$controllerProvider

更新的測試代碼如下:

describe("ChildCtrl", function() { 
    var BaseCtrl; 

    beforeEach(module('my-module', function ($controllerProvider) { 
     BaseCtrl = jasmine.createSpy(); 
     BaseCtrl.$inject = ['$scope', 'frobnicate']; 

     $controllerProvider.register('BaseCtrl', BaseCtrl); 
    })); 

    beforeEach(inject(function ($controller, $rootScope) { 
     $controller('ChildCtrl', { $scope: $rootScope.$new() }); 
    })); 

    it("inherits from BaseCtrl", inject(function ($controller, $rootScope) { 
     expect(BaseCtrl).toHaveBeenCalled(); 
    })); 

    it("passes frobnicate() function to BaseCtrl that returns 123", function() { 
     var args = BaseCtrl.calls.argsFor(0); 
     var frobnicate = args[1]; 

     expect(frobnicate()).toEqual(123); 
    }); 
});