测试if条件内启动的非作用域方法中的作用域变量:如何触发init()?
解决测试中无法触发
init()方法的问题 咱们先理清楚问题根源:
- 你的业务代码里,
if($scope.someValue){ init(); }是在init函数定义之前执行的——这意味着初始化时如果someValue为true,这里会直接报错(因为init还没被赋值); - 测试中你设置
$scope.someValue = true后,那个if语句不会重新执行,因为它只在代码加载时跑一次,所以init()根本没被调用,自然$scope.anotherVal还是undefined,导致测试失败。
下面给你两种可行的解决办法:
方法一:用$watch监听someValue的变化(推荐)
修改业务代码,让someValue变化时自动触发init(),这样不管是初始化还是后续修改,都能正确执行:
// 先定义init函数,避免变量提升导致的未定义问题 var init = function(){ $scope.anotherVal = true; } // 监听someValue的变化,值变为true时执行init $scope.$watch('someValue', function(newValue) { if (newValue) { init(); } }); // 初始化时也检查一次初始值 if ($scope.someValue) { init(); }
对应的测试用例需要触发Angular的消化循环(digest cycle),让$watch检测到变量变化:
describe('test 1', function(){ it('spec 1', function(){ $scope.someValue = true; // 触发digest循环,触发watch回调 $scope.$digest(); expect($scope.anotherVal).toEqual(true); }); });
方法二:测试中手动调用init()(仅当init可访问时)
如果你的业务代码结构暂时不能改,且init函数在测试的作用域内可访问,那可以直接在测试里手动调用它:
describe('test 1', function(){ it('spec 1', function(){ $scope.someValue = true; // 直接调用init方法 init(); expect($scope.anotherVal).toEqual(true); }); });
⚠️ 注意:如果init是私有变量(比如在闭包里),这个方法就不适用了,还是优先用方法一的$watch方案,它更符合Angular的响应式设计。
内容的提问来源于stack exchange,提问作者V Reddy
相关产品推荐
相关产品推荐

