下面我有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();
});
});
答案 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