AngularJS $超时function不执行在我的茉莉花规格

我试图用茉莉花来testing我的AngularJS控制器,使用Karma。 但是在现实生活中运行良好的$timeout会使我的testing崩溃。

控制器:

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

茉莉花块( $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将为true。 但是在我的testing中, $timeout什么也不做,函数永远不会执行,Jasmine会在超过750 ms后报错。 这里有什么可能是错的?

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

尝试更新你的testing:

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

这是一个显示你原来的testing失败和新的testing通过的笨蛋 。

正如其中一个评论所述,茉莉花setTimeout模拟没有被使用,因为angularJS的模拟$timeout服务被用来代替。 就个人而言,我宁愿使用茉莉花的,因为它的嘲笑方法让我testing超时的长度。 你可以在你的unit testing中用一个简单的提供者有效地规避它:

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

注意:如果你走这条路线,一定要在jasmine.Clock.tick之后调用$scope.apply()

由于$timeout只是window.setTimeout一个包装,所以你可以使用Clock.useMock()Clock.useMock() window.setTimeout

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