在 Jasmine/Karma 中测试 $interval

Testing $interval in Jasmine/ Karma

我有一个简单的工厂

angular.module('myApp.dice',[]).factory('Dice', ['$interval', function($interval){
    return {
      rollDice: function(){
        return $interval(function(c){
               count++;
          }, 100, 18, false, 0);
      }
    };
}]);

在我的测试用例中我有

describe('rolling dice', function(){
      var promise, promiseCalled = false, notify = false;
      beforeEach(inject(function(){
        promise = Dice.rollDice();
        promise.then(function(){
          promiseCalled = true;
        });

      }));

      it('should invoke a promise', inject(function(){
        expect(promise).toBeDefined();
      }));

      it('should set promiseCalled', inject(function($rootScope, $interval){


        expect(promiseCalled).toEqual(true);
      }));
    });

如何触发间隔或解决承诺?让测试是真的?

plunker

您需要使用 angularjs-mocks 中的 '$interval.flush' 然后测试结果。我冒昧地将 count 分配给 dice 对象,因为它在您的代码示例中未定义。

invokeApply = false调用$interval有什么原因吗?因为那时你必须手动调用 $apply.

测试用例为:

describe('rolling dice', function(){
    var $interval, $rootScope, dice;

    beforeEach(module('plunker'));

    beforeEach(inject(function(_$interval_, _$rootScope_, _Dice_){
      $interval = _$interval_;
      $rootScope = _$rootScope_;
      dice = _Dice_;
    }));

    it('should increment count', inject(function(){
      dice.rollDice();
      // Move forward by 100 milliseconds
      $interval.flush(100);
      // Need to call apply because $interval was called with invokeApply = false
      $rootScope.$apply();
      expect(dice.count).toBe(1);
    }));
  });

与工厂:

app.factory('Dice', ['$interval', function($interval){
    var self= {
      count: 0,
      rollDice: function(){
        return $interval(function() {
              self.count++;
          }, 100, 18, false, 0);
      }
    };
    return self;
}]);

编辑: 我更喜欢测试函数调用的结果,但也许您有一个用例来测试调用了 promise 函数,所以这可能就是您要找的。从 $interval 上的 angular 文档中可以看出 returns

A promise which will be notified on each iteration.

关键字正在通知promise API then 的参数是

then(successCallback, errorCallback, notifyCallback)

即第三个回调函数 notifyCallback$interval 的每次迭代中被调用。所以测试看起来像这样:

it('should set promiseCalled', function(){
  var promiseCalled = false;
  dice.rollDice().then(null, null, function() {
    promiseCalled = true;
  });
  $interval.flush(100);
  $rootScope.$apply();
  expect(promiseCalled).toBe(true);
});

如果你想测试一个已解决的承诺,那么它看起来像这样:

it('should resolve promise', function(){
  var promiseCalled = false;
  var resolvedData = null;
  $q.when('Some Data').then(function(data) {
    promiseCalled = true;
    resolvedData = data;
  });
  $rootScope.$apply();
  expect(promiseCalled).toBe(true);
  expect(resolvedData).toBe('Some Data');
});

我已经用这些测试用例更新了 plunker。