使用Jasmine进行测试时,请注意不要触发

时间:2014-06-16 11:47:19

标签: javascript angularjs unit-testing testing jasmine

我正在尝试测试我的$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没有被解雇?

3 个答案:

答案 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);

DEMO

答案 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();
})