是否可以测试Angular控制器的init进程?
以下是代码:
var app = angular.module('led', []);
app.controller('zeppelin', ['$scope', function ($scope) {
$scope.love = function () {
return 2;
};
$scope.tangerine = $scope.love();
$scope.prove = function () {
$scope.love();
};
$scope.prove();
$scope.love();
}]);
测试代码:
scope = _$rootScope_.$new();
controller = _$controller_('zeppelin', {
$scope: scope
});
proved = sinon.spy();
loved = sinon.stub().returns(7);
scope.prove = proved;
scope.love = loved;
expect(proved.callCount).toBe(1); //=> 0
expect(loved.callCount).toBe(2); //=> 0
scope.prove();
expect(proved.callCount).toBe(2); //=> 1
expect(loved.callCount).toBe(3); //=> 0
我对上述代码的问题是:
对我来说,最好的情况是 3 ,因为我无法想到对这种奇怪行为的任何合理解释。
答案 0 :(得分:1)
<强> 1 强>
控制器只是一个接受$scope
对象作为参数的构造函数。您正在定义范围
$scope.love = function () {
return 2;
};
$scope.prove = function () {
$scope.love();
};
然后立即调用它们
$scope.prove();
$scope.love();
在控制器结束时首次调用函数之前,无法拦截此过程(在Angular中或一般情况下)监视函数。如果您在初始化控制器之前设置了$scope.prove = spied
,那么控制器就会覆盖它,如果您在之后设置,那么当间谍将不存在时这些函数被调用。
<强> 2 强>
由于上述原因,您无法及时存根$scope.love
,以便将其返回值分配给$scope.tangerine
。如果能够在测试中修改控制器初始化行为对您来说真的很重要,那么您应该使love
和注入服务将其注入控制器,并在测试中模拟它。
第3 强>
您的间谍($scope.prove
)会覆盖 scope.prove = proved
。您正在丢失在控制器中创建的原始函数,该函数调用$scope.love
。相反,你需要监视现有的功能。例如,
var controller = $controller('zeppelin', { $scope: scope });
// here, the controller has initialized scope.prove and scope.love
var loved = sinon.spy(scope, 'love');
var proved = sinon.spy(scope, 'prove');
scope.prove();
// both callCounts are incremented
expect(proved.callCount).toBe(1);
expect(loved.callCount).toBe(1);
答案 1 :(得分:0)
看起来只有范围才能在控制器的init进程上进行测试。可以测试任何其他依赖项,因为事先知道它们的状态。
一些确认代码:
app.controller('zeppelin', ['$scope','hangman', function ($scope, hangman) {
$scope.love = function () {
hangman.a(4,6);
return 'sweet';
};
$scope.tangerine = $scope.love();
$scope.prove = function () {
$scope.love();
hangman.a(4,$scope.tangerine);
};
hangman.a(4,6);
}]);
测试代码:
beforeEach(inject(function (_$rootScope_, _$controller_, _hangman_) {
sandbox = sinon.sandbox.create();
scope = _$rootScope_.$new();
hangman = _hangman_;
blackDog = sinon.spy(hangman, 'a');
loved = sinon.spy(scope, 'love');
controller = _$controller_('zeppelin', {
$scope: scope,
hangman: hangman
});
proved = sinon.spy(scope, 'prove');
}));
it('should x', function () {
scope.prove();
scope.love();
expect(scope.tangerine).toBe('sweet');
expect(loved.callCount).toBe(2);
expect(blackDog.callCount).toBe(5);
expect(proved.callCount).toBe(1);
});