AngularJS $超时功能没有在我的Jasmine规范中执行

时间:2013-06-27 18:20:05

标签: angularjs jasmine

我正在尝试使用Karma使用Jasmine测试我的AngularJS控制器。但是$timeout在现实生活中运作良好,会使我的测试崩溃。

控制器:

var Ctrl = function($scope, $timeout) {
  $scope.doStuff = function() {
    $timeout(function() {
      $scope.stuffDone = true;
    }, 250);
  };
};

Jasmine阻止($scope和控制器已正确初始化):

it('should do stuff', function() {
  runs(function() {
    $scope.doStuff();
  });
  waitsFor(function() { 
    return $scope.stuffDone; 
  }, 'Stuff should be done', 750);
  runs(function() {
    expect($scope.stuffDone).toBeTruthy();
  });
});

当我在浏览器中运行我的应用时,$timeout功能将被执行,$scope.stuffDone将成立。但是在我的测试中,$timeout什么也没做,函数永远不会被执行,并且Jasmine在超过750毫秒后报告错误。这可能有什么问题?

3 个答案:

答案 0 :(得分:76)

根据$timeout的Angular JS文档,您可以使用$timeout.flush()同步刷新延迟函数的队列。

尝试将测试更新为:

it('should do stuff', function() {
  expect($scope.stuffDone).toBeFalsy();
  $scope.doStuff();
  expect($scope.stuffDone).toBeFalsy();
  $timeout.flush();
  expect($scope.stuffDone).toBeTruthy();
});

这是plunker,显示原始测试失败和新测试通过。

答案 1 :(得分:9)

正如其中一条评论中所述,Jasmine setTimeout mock未被使用,因为使用了角度的JS模拟$timeout服务。就个人而言,我宁愿使用Jasmine,因为它的模拟方法让我测试超时的长度。您可以在单元测试中使用简单的提供程序有效地规避它:

module(function($provide) {
  $provide.constant('$timeout', setTimeout);
});

注意:如果你走这条路,请务必在jasmine.Clock.tick之后拨打$scope.apply()

答案 2 :(得分:4)

由于$timeout只是window.setTimeout的包装,您可以使用jasmines Clock.useMock()来模仿window.setTimeout

  beforeEach(function() {
    jasmine.Clock.useMock();
  });

  it('should do stuff', function() {
    $scope.doStuff();
    jasmine.Clock.tick(251);
    expect($scope.stuffDone).toBeTruthy();
  });