我正在尝试测试我的$watch
听众,但是,它没有在测试中开火。
以下是测试:
it('should fire $watch when selectedBrands change', function() {
spyOn($scope, 'updateFilters')
$scope.selectedBrands = ['1'];
expect($scope.updateFilters).toHaveBeenCalled();
})
控制器:
$scope.selectedBrands = [];
$scope.$watch("selectedBrands", function() {
$scope.updateFilters();
}, true);
最后,错误:
Chrome 35.0.1916 (Mac OS X 10.10.0) ItemsController should fire $watch when selectedBrands change FAILED
Expected spy updateFilters to have been called.
Error: Expected spy updateFilters to have been called.
at null.<anonymous> (/Applications/MAMP/htdocs/cloqet_client/testing/tests/ItemModule/ItemsController_spec.js:62:38)
我尝试使用$scope.$digest()
,但即使不更改$scope.selectedBrands
也会使测试通过。
为什么$watch
没有被解雇?
答案 0 :(得分:3)
使用$scope.$digest()
来触发摘要是正确的。
it('should fire $watch when selectedBrands change', function() {
spyOn($scope, 'updateFilters')
$scope.selectedBrands = ['1'];
$scope.$digest();
expect($scope.updateFilters).toHaveBeenCalled();
});
但这使测试通过甚至没有改变 $ scope.selectedBrands
原因是$ watch 总是第一次使用undefined
触发,即使您没有更改该值。当前测试反映了当前代码的正确行为。这意味着您的代码有一个需要修复的错误。
要解决此问题,请尝试修复代码:
$scope.$watch("selectedBrands", function(value) {
if (value){ //check for undefined fired the first time.
$scope.updateFilters();
}
}, true);
答案 1 :(得分:1)
测试在Angular-context之外运行,因此没有自动的$ digest循环发生
$watch()
未被触发,因为您需要首先手动调用$ digest循环。
您还应该记住,每次$ watch回调都会执行一次以初始化值
这就是为什么即使不更改$scope.updateFilter()
,您的selectedBrands
也会被调用
引用 the docs :
&#34;观察者在范围内注册后,listener
fn被异步调用(通过$evalAsync)来初始化观察者。&#34;
测试它的正确方法是手动调用$ digest循环(因此$ watch初始化),然后更改selectedBrands
并最终调用secod $ digest循环到&#34; digest&# 34;那种变化。
E.g:
it('should fire $watch when selectedBrands change', function() {
$scope.$digest();
spyOn($scope, 'updateFilters');
$scope.selectedBrands = ['1'];
$scope.$digest();
expect($scope.updateFilters).toHaveBeenCalled();
});
另请参阅此 short demo 。
答案 2 :(得分:0)
你需要一个摘要过程才能被解雇,那就是当观察者做检查时
it('should fire $watch when selectedBrands change', function() {
spyOn($scope, 'updateFilters')
$scope.selectedBrands = ['1'];
$scope.$digest()
expect($scope.updateFilters).toHaveBeenCalled();
})