Fake timers

JavaScript code on various platforms makes heavy use of the global timer functions – setTimeout() etc. – and when testing such code it’s often good to be able to take control of the clock to drive a test scenario forward. This means that, rather than setting your own timeouts in tests to wait for things to happen, you can tell the clock to tick forward and run your timeouts. This speeds your tests up and removes some of the line noise of running asynchronous tests.

JS.Test.FakeClock lets you stub out JavaScript’s clock and move time forward yourself. To use it, you need to add the following hooks to your tests:

JS.Test.describe('Timers', function() { with(this) {
  include(JS.Test.FakeClock)

  before(function() { this.clock.stub() })
  after(function() { this.clock.reset() })

  // Your tests here
}})

Calling clock.stub() replaces the global time functions – Date(), Date.now(), setTimeout(), clearTimeout(), setInterval() and clearInterval() – with versions that run on a fake clock that you control. They work just like the real versions, only that time is now controlled by you rather than by the JavaScript runtime.

When using FakeClock, timers will not execute unless you advance the clock. To make time tick forward, use the clock.tick() method:

// Advances time 1000 milliseconds
this.clock.tick(1000)

Let’s take a quick example. This test sets a timeout to change the value of a string, and we use FakeClock to test it:

JS.Test.describe('Timers', function() { with(this) {
  include(JS.Test.FakeClock)

  before(function() { this.clock.stub() })
  after(function() { this.clock.reset() })

  before(function() { with(this) {
    this.string = 'foo'
    setTimeout(function() { string = 'bar' }, 100)
  }})

  it('changes a string', function() { with(this) {
    assertEqual('foo', string)
    clock.tick(100)
    assertEqual('bar', string)
  }})
}})