AngularJS $timeout function not executing in my Jasmine specs

泪湿孤枕 提交于 2019-12-03 14:25:38

问题


I'm trying to test my AngularJS controller with Jasmine, using Karma. But a $timeout which works well in real-life, crashes my tests.

Controller:

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

Jasmine it block (where $scope and controller have been properly initialized):

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

When I run my app in browser, $timeout function will be executed and $scope.stuffDone will be true. But in my tests, $timeout does nothing, the function is never executed and Jasmine reports error after timing out 750 ms. What could possibly be wrong here?


回答1:


According to the Angular JS documentation for $timeout, you can use $timeout.flush() to synchronously flush the queue of deferred functions.

Try updating your test to this:

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

Here is a plunker showing both your original test failing and the new test passing.




回答2:


As noted in one of the comments, Jasmine setTimeout mock is not being used because angular's JS mock $timeout service is used instead. Personally, I'd rather use Jasmine's because its mocking method lets me test the length of the timeout. You can effectively circumvent it with a simple provider in your unit test:

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

Note: if you go this route, be sure to call $scope.apply() after jasmine.Clock.tick.




回答3:


As $timeout is just a wrapper for window.setTimeout, you can use jasmines Clock.useMock() which mocks the window.setTimeout

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

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


来源:https://stackoverflow.com/questions/17350492/angularjs-timeout-function-not-executing-in-my-jasmine-specs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!