如何使用Jasmine的去抖功能测试AngularJS手表

gwh*_*whn 6 jasmine angularjs karma-jasmine

我有一个带有手表的控制器,它使用来自lodash的debounce延迟过滤列表500ms.

$scope.$watch('filter.keywords', _.debounce(function () {
  $scope.$apply(function () {
    $scope.filtered = _.where(list, filter);
  });
}, 500));
Run Code Online (Sandbox Code Playgroud)

我想写一种模拟输入未发现之后所发现的关键词过滤关键字茉莉花测试.

我最初的尝试是在为关键字分配一个新值后使用$ digest,我认为这是因为去抖而无效.

it('should filter list by reference', function () {
  expect(scope.filtered).toContain(item);
  scope.filter.keywords = 'rubbish';
  scope.$digest();
  expect(scope.filtered).not.toContain(item);
  scope.filter.keywords = 'test';
  scope.$digest();
  expect(scope.filtered).toContain(item);
});
Run Code Online (Sandbox Code Playgroud)

所以我尝试使用$ timeout,但这也不起作用.

it('should filter list by reference', function () {
  expect(scope.filtered).toContain(item);
  $timeout(function() {
    scope.filter.keywords = 'rubbish';
  });
  $timeout.flush();
  expect(scope.filtered).not.toContain(item);
  $timeout(function() {
    scope.filter.keywords = 'test';
  });
  $timeout.flush();
  expect(scope.filtered).toContain(item);
});
Run Code Online (Sandbox Code Playgroud)

我还尝试给$ timeout一个大于debounce设置的500ms的值.

其他人如何解决这个问题?

编辑:我找到了一个解决方案,它将期望包装在$ timeout函数中,然后在范围上调用$ apply.

it('should filter list by reference', function () {
  expect(scope.filtered).toContain(item);
  scope.filter.keywords = 'rubbish';
  $timeout(function() {
    expect(scope.filtered).not.toContain(item);
  });
  scope.$apply();
  scope.filter.keywords = 'test';
  $timeout(function() {
    expect(scope.filtered).toContain(item);
  });
  scope.$apply();
});
Run Code Online (Sandbox Code Playgroud)

我仍然有兴趣知道这种方法是否最好.

Fla*_*ape 4

这是一个糟糕的做法。您应该使用特定于角度的去抖动,例如使用$timeout 而不是 setTimeout。这样,你就可以做

  $timeout.flush();
  expect(scope.filtered).toContain(item);
Run Code Online (Sandbox Code Playgroud)

并且规范将按预期通过。