AngularJS $timeout function not executing in my Jasmine specs

前端 未结 3 1478
醉话见心
醉话见心 2021-02-06 21:42

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:



        
相关标签:
3条回答
  • 2021-02-06 22:24

    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.

    0 讨论(0)
  • 2021-02-06 22:42

    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();
      });
    
    0 讨论(0)
  • 2021-02-06 22:44

    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.

    0 讨论(0)
提交回复
热议问题