如何使用Jasmine的debounce函数测试AngularJS手表
我有一个带手表的控制器,它使用lodash的去盎司延迟过滤列表500毫秒如何使用Jasmine的debounce函数测试AngularJS手表,angularjs,jasmine,karma-jasmine,Angularjs,Jasmine,Karma Jasmine,我有一个带手表的控制器,它使用lodash的去盎司延迟过滤列表500毫秒 $scope.$watch('filter.keywords', _.debounce(function () { $scope.$apply(function () { $scope.filtered = _.where(list, filter); }); }, 500)); 我试图编写一个Jasmine测试,模拟输入未找到的筛选关键字,然后输入已找到的关键字 我最初的尝试是在为关键字分配了一个新值后
$scope.$watch('filter.keywords', _.debounce(function () {
$scope.$apply(function () {
$scope.filtered = _.where(list, filter);
});
}, 500));
我试图编写一个Jasmine测试,模拟输入未找到的筛选关键字,然后输入已找到的关键字
我最初的尝试是在为关键字分配了一个新值后使用$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);
});
所以我尝试使用$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);
});
我也尝试过给$timeout一个大于去盎司500毫秒的值
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);
});
其他人是如何解决这个问题的
EDIT:我找到了一个解决方案,将期望值封装在$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();
});
我仍然有兴趣知道这种方法是否是最好的。这是一种糟糕的方法。您应该使用特定于角度的去抖动,例如使用$timeout而不是setTimeout。那样的话,你可以做到
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();
});
$timeout.flush();
expect(scope.filtered).toContain(item);
该规范将按预期通过。使用spyOn替换uu.debounce,检查此链接 我用过这个:
beforeEach(function() {
...
spyOn(_, 'debounce').and.callFake(function (fn) {
return function () {
//stack the function (fn) code out of the current thread execution
//this would prevent $apply to be invoked inside the $digest
$timeout(fn);
};
});
});
function digest() {
//let the $watch be invoked
scope.$digest();
//now run the debounced function
$timeout.flush();
}
it('the test', function() {
scope.filter.keywords = ...;
digest();
expect(...);
});
希望能有帮助