jasmine.clock()。tick()与$ timeout和debounce无效,但与setTimeout一起工作正常

时间:2014-08-01 09:47:08

标签: javascript angularjs jasmine leaflet lodash

下面我有3个完全相同的功能。每个使用不同的方式调用setTimeout,delay1()直接使用setTimeout,delay2()使用angularjs $ timeout和delay3()使用lodash debounce。它们都很好。

使用Jasmine进行测试时会出现问题。使用jasmine.clock()。tick()方法,setTimeout工作正常,但$ timeout和debounce不是

我有兴趣与Jasmine合作进行辩护。我知道我可以使用带有angularjs的$ timeout.flush()但$ timeout和setTimeout在我的代码中的其他地方给我带来问题,我在传单中使用它。 debounce与传单很好地配合。

我在这里创建了一个plunker:plnkr你会看到$ timeout和debounce测试在setTimeout测试通过时没有通过。

有没有办法可以解决这个问题?感谢

JS

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope, $timeout) {
  $scope.name = 'World';
  $scope.delayed1 = function(){
    setTimeout(function(){
      $scope.name = "Hello world by setTimeout";
    },500)
  }
  $scope.delayed2 = function(){
    $timeout(function(){
      $scope.name = "Hello world by $timeout";
    },500)
  }
  $scope.delayed3 = function(){
    _.debounce(function(){
      $scope.name = "Hello world by debounce";
    },500)
  }
});

规范

describe('Testing a Hello World controller', function() {
  var $scope = null;
  var ctrl = null;

  //you need to indicate your module in a test
  beforeEach(module('plunker'));

  beforeEach(inject(function($rootScope, $controller) {
    $scope = $rootScope.$new();

    ctrl = $controller('MainCtrl', {
      $scope: $scope
    });
  }));

  it('should say hallo to the World', function() {
    expect($scope.name).toEqual('World');
  });
  it('should say Hello world by setTimeout', function() {
    jasmine.clock().install();
    $scope.delayed1();
    jasmine.clock().tick(600);
    expect($scope.name).toEqual('Hello world by setTimeout');
    jasmine.clock().uninstall();

  });
  it('should say Hello world by timeout', function() {
    jasmine.clock().install();
    $scope.delayed2();
    jasmine.clock().tick(600);
    expect($scope.name).toEqual('Hello world by timeout');
    jasmine.clock().uninstall();

  }); 
  it('should say Hello world by debouce', function() {
    jasmine.clock().install();
    $scope.delayed3();
    jasmine.clock().tick(600);
    expect($scope.name).toEqual('Hello world by debouce');
    jasmine.clock().uninstall();

  }); 
});

3 个答案:

答案 0 :(得分:19)

Jasmine中的时钟只有在您直接测试setInterval()setTimeout()函数时才有效,因为它只是嘲笑那些专门同步运行的函数。我相信有一个拉动请求让Jasmine模拟Date对象,这样可以测试像_.debounce()这样的函数而不会嘲笑它,但是我不记得是否合并过它。

要测试_.debounce(),您必须模拟它以同步运行,最好是作为间谍,或者您可以覆盖该功能。以下是我发现为我工作的内容:

spyOn(_, 'debounce').and.callFake(function (func) {
    return function () {
        func.apply(this, arguments);
    };
});

现在对_.debounce()的调用将同步运行,测试应该成功完成。当然,你仍然需要使用$timeout.flush()

我使用这些更改更新了您的plunker:http://plnkr.co/edit/KXmwcf1faUNf8nlqPeyd

答案 1 :(得分:1)

除了@ JDWardle的回答,你可能还想为debounce取消方法创建一个间谍。

spyOn(_, 'debounce').and.callFake(function (func) {
    var mockDebounce = function () {
        func.apply(this, arguments);
    };
    mockDebounce.cancel = jasmine.createSpy('cancel');
    return mockDebounce;
});

答案 2 :(得分:0)

lodash中的去抖功能使用Date对象。您可以像这样使用Date模拟jasmine对象:

jasmine.clock().install();
jasmine.clock().mockDate();

jasmine.clock().tick(1000); // trigger the debounce

来源:https://jasmine.github.io/2.9/introduction.html#section-Mocking_the_Date