Fake Timers with SinonJs


Tests suites tend to grow together with applications. It is quite common that you need a significant amount of time to execute all your unit tests. Under these circumstances, you cannot afford to waste 5 secons on waiting for a setTimeout callback. Technically, even if you could, increasing the waiting time even further would eventually cause a timeout, resulting in a failed test.

We still need to find a way to test functionality where a setTimeout or a setInterval is present. This is what SinonJs fake timers are for. We can freeze time with SinonJs and fast-forward it to a time instant we would like to verify.

Freezing the Timer

Freezing the timer is done by calling the useFakeTimers method of the sinon object. Don’t forget to store the reference of the timer.

As soon as you call the useFakeTimers method, time will stop. You can start executing the tested code and verify the intended behavior after you make some time pass. For instance, the following code won’t do anything as the timer is not running. Don’t wait for the console log to appear.

Time can be advanced by calling the tick method of your clock object and passing it a value in milliseconds.

You will always know how much fake time has passed since creating the clock object. The tick method returns the number of fake milliseconds passed since useFakeTimers was called. Therefore, you can formulate your expectations at the right time even if there are complex timing dependencies in your application.

Make sure you use the right boundary values in your tests. If an animation takes 2 seconds to execute, don’t advance the clock by 7.5 seconds. Similarly to your CSS files, your tests should not contain magic numbers. Therefore, using the boundary value of 2 seconds is suggested before verifying that the animation is done.

Once you don’t need the fake timer, restore it:

Use cases and constraints

Use cases:

  • Animations
  • Verifying periodic polling updating data on our page
  • Any timing constraints formulated by setTimeout and setInterval

Fake timers save you time. Your test suite does not have to wait until the setTimeout or setInterval callback is fired.

Constraints:

  • Do not expect the fake timer to freeze ongoing animations
  • Always test your functionality moving forward in time, rewinding is not reliable

Testing timing constraints

Suppose the following CSS class is given.

Let’s move a square on the screen and verify its position.

The associated tests show how the animation can be exercised.

While performing the animations may take even seconds, the three tests are executed in a fraction of a second. In fact, all 95 of our tests are executed in less than a second in the browser. Check it out on GitHub!

Summary

Fake the time for testing animations or any piece of functionality that is scheduled to be executed in the future. Take control of the timer, save its reference, start the piece of functionality containing setTimeout or setInterval and advance the timer forward. Verify the state of the application without waiting for the timing constraints in real time.

This was part seven of the test automation series on Mocha, Chai, and SinonJs. If you are interested in reading more on test automation, check out the complete series by clicking here. In the next article, we will set up a fake server with SinonJs.

Learn ES6 in Practice

Sign up below to access an ES6 course with many exercises and reference solutions.