Recently at a client, a question came up about unit testing functionality that used setTimeout and setInterval. The issue in this particular case was that there were several additional locations where and had been implemented ... and the complete codebase needs to run before testing. Because all code runs, there are "bleed over" cases where code is interfering with the tests. setTimeout setInterval other The Pattern The pattern discussed would allow for both sets of functionality to be wrapped in such a way that they can be removed, as needed. This functionality allowed the IDs to be stored in a way that they could be removed as the tests iterated. This pattern is using a pattern I am somewhat uncomfortable with as a tester, but given the amount of code already in place, this seemed like a reasonable option. a patch timeoutIds = []; intervalIds = []; windowSetTimeout = .setTimeout; windowSetInterval = .setInterval; .setTimeout = { id = windowSetTimeout.apply( , ) timeoutIds.push(id); id; }; .setInterval = { id = windowSetInterval.apply( , ) intervalIds.push(id); id; }; afterEach( { timeoutIds.forEach( .clearTimeout); intervalIds.forEach( .clearInterval); timeoutIds = []; intervalIds = []; }); var var var window var window window ( ) function testSetTimeout var this arguments return window ( ) function testSetInterval var this arguments return ( ) function window window setTimeout Now, having shown this pattern, I found a few other options that, while they seemed more reasonable, did not fit well with this established codebase. The following examples were primarily derived from How to test a function which has a setTimeout with jasmine? Part of the issue I see with these examples is that is not covered. setInterval Given a function with a timeout inside: testableVariable = ; { setTimeout( { testableVariable = ; }, ); } var false ( ) function testableCode ( ) function true 10 Use as a means to tell the test that the will be checked Asynchronously, allowing enough time to expire for the setTimeout in the code above to run ... done expect it( , { testableCode(); setTimeout( { expect(testableVariable).toEqual( ); done(); }, ); }); 'expects testableVariable to become true' ( ) function done ( ) function true 20 Additionally, the timer behavior could be mocked - this method allows to step the time forward. jasmine it( , { jasmine.clock().install(); testableCode(); jasmine.clock().tick( ); expect(testableVariable).toEqual( ); jasmine.clock().uninstall(); }); 'expects testableVariable to become true' ( ) function 10 true And, we can now use from async/await Asynchronous Work it( , { testableCode(); expect(testableVariable).toEqual( ); }); 'expects testableVariable to become true' async ( ) function await true Also, the original code could be refactored to take the function inside the out in a way to make it testable. setTimeout testableVariable = ; { testableVariable = ; } { setTimeout(testableAfterTimeout, ); } var false ( ) function testableAfterTimeout true ( ) function testableCode 10 With this code, we can simply test the function directly. testableAfterTimeout it( , { testableAfterTimeout(); expect(testableVariable).toEqual( ); }); 'expects testableVariable to become true' ( ) function true setInterval Looking at another example: testableVariable2 = ; { counter = ; interval = setInterval( { (counter === ){ testableVariable = ; clearInterval(interval); } counter++; }, ); interval; } var false ( ) function testableCode2 var 1 var ( ) function if 5 true 500 return In this case, we should be able to see that the previous test patterns should work in our favor here. Use as a means to tell the test that the will be checked Asynchronously, allowing enough time to expire for the setTimeout in the code above to run. done expect it( , { testableCode2(); setTimeout( { expect(testableVariable2).toEqual( ); done(); }, ); }); 'expects testableVariable2 to become true' ( ) function done ( ) function true 4000 Additionally, the timer behavior could be mocked - this method allows to step the time forward. jasmine it( , { jasmine.clock().install(); testableCode2(); jasmine.clock().tick( ); expect(testableVariable2).toEqual( ); jasmine.clock().uninstall(); }); 'expects testableVariable2 to become true' ( ) function 4000 true Also, the original code could be refactored to take the function inside the out in a way to make it testable. setInterval testableVariable2 = ; counter = ; interval; { (counter === ){ testableVariable = ; clearInterval(interval); } counter++; } { counter = interval = setInterval(testableAfterInterval, ); interval; } var false var 1 var ( ) function testableAfterInterval if 5 true ( ) function testableCode2 1 500 return With this code, we can simply test the function directly. testableAfterInterval it( , { counter = ; testableAfterInterval(); expect(testableVariable2).toEqual( ); }); 'expects testableVariable2 to become true' ( ) function 5 true Conclusion There are many means of handling Asynchronous behavior. I've only mentioned a few here (and in a specific test framework). These are simply a few patterns that can be used when these cases come up. Also published at https://dev.to/rfornal/testing-settimeout-setinterval-22ff