场景是我有一个ChildCtrl控制器,继
this inheritance pattern之后继承BaseCtrl:
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 instantiated”,表明$controller正在使用实际的控制器而不是我提供的$provide.value()实例.
测试这个的最佳方法是什么?
解决方法
所以看起来$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,{ $scope: $rootScope.$new() }); })); it("inherits from BaseCtrl",$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); }); });