Jasmine.clock (). tick () does not work with $ timeout and debounce, but works fine with setTimeout

Below I have 3 functions that do the same. Each uses a different way to call setTimeout, delay1 () uses setTimeout directly, delay2 () uses angularjs $ timeout, and delay3 () uses lodash debounce. Everything is working fine.

Problems arise when I test Jasmine. setTimeout works great with the jasmine.clock () method. tick (), but $ timeout and debounce are not

I am interested in canceling work with Jasmine. I know I can use $ timeout.flush () with angularjs, but $ timeout and setTimeout give me problems elsewhere in my code where I use it with booklet maps. debounce works with an elevator.

I created a plunker here: plnkr , where you will see that the $ timeout and debounce tests do not pass while the setTimeout test passes.

Is there any way around this problem? Thanks

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) } }); 

specifications

 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(); }); }); 
+6
source share
3 answers

A clock in Jasmine will only work if you are testing the setInterval() or setTimeout() functions, as they simply wear out these functions specifically for synchronous launch. I believe that Jasmine’s request for bullying a Date object that allows you to test functions like _.debounce() without bullying, I don’t remember if it was combined or not.

To test _.debounce() , you will have to mock it running synchronously, preferably as a spy, or you can simply override this function. Here is what I found for me to work:

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

Now the _.debounce() calls will be executed synchronously, and the tests should complete successfully. Of course, you still have to use $timeout.flush() .

I updated your pluker with these changes: http://plnkr.co/edit/KXmwcf1faUNf8nlqPeyd

+19
source

In addition to @JDWardle's answer, you can also create a spy for the debounce cancellation method.

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

The debounce function from lodash uses a Date object. You are mocking a Date object using jasmine like this:

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

Source: https://jasmine.imtqy.com/2.9/introduction.html#section-Mocking_the_Date

0
source

Source: https://habr.com/ru/post/973215/


All Articles