如何模拟angularjs测试中的时间传递?

时间:2014-07-30 22:56:14

标签: angularjs angularjs-directive timeout jasmine

我试图通过angularjs jasmine测试传递模拟时间。

我正在测试的指令只显示当前时间并每秒更新一次:

return {
  restrict: 'A',
  scope: {
    format: '@'
  },
  link: function (scope, element, attrs) {

    var timeout;

    function updateElement() {
      if (scope.format) {
        element.text($filter('date')(new Date(), scope.format));
      }
    }

    function updateTime() {
      updateElement();
      timeout = $timeout(function () {
        updateTime();
      }, 1000);
    }

    element.bind('$destroy', function () {
      $timeout.cancel(timeout);
    });

    updateTime();
  }
};

在我的测试中,我需要模拟时间的流逝。我尝试使用$ timeout和$ timeout.flush,但我认为我错了:

it('should update every second', function () {
  $scope.$digest();
  console.log('before: ' + element.text());
  var before = element.text();

  // Wait for a couple seconds...
  $timeout(function () {
    $scope.$digest();
    console.log('after: ' + element.text());
    expect(element.text()).not.toEqual(before);
  }, 5000);

  $timeout.flush(5000);
});

我应该使用$ timeout来模拟经过的时间,还是他们的另一种方法呢?

Plunker:http://plnkr.co/edit/0V4AFGXqSfc9iLCuZbvn?p=preview

1 个答案:

答案 0 :(得分:1)

如果将$scope.$digest()包裹在setTimeout内,它应该有效。像这样:

setTimeout(function(){
  $timeout.flush();
  console.log('after: ' + element.text());
  expect(element.text()).not.toEqual(before);
}, 5000);

$timeout.flush()只需调用$timeout注册的所有回调,无论其时间值如何,都可以在测试中工作,因此在这种情况下,您必须在角度之外执行超时。由于您每秒钟只需要更改一次,因此您的代码会在一秒钟内调用updateElement()两次。