2014-12-04 88 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); 
    }); 
});