title: How do I test a recursive, asynchronous JavaScript function using fake timers?
body: <p>I have a basic recursive function, which works correctly when executed. I would like to use Sinon's fake timers to test the function at each stage of execution.</p>
  <p>However, it seems that the fake timers are only applying to the first call of the recursive function.</p>
  <p>I'm curious if anyone can help figure out how to get the fake timers working all the way through.</p>
  <p><strong>Example:</strong></p>
  <pre><code>function wait(ms) {
    return new Promise(resolve =&gt; setTimeout(resolve, ms))
  }
  
  async function ensureCount(count, { attempt, delay }) {
    attempt = attempt || 0
    console.log('Attempt', attempt)
  
    if (attempt === count) {
      return
    }
  
    await wait(delay)
    await ensureCount(count, { attempt: attempt + 1, delay })
  }
  </code></pre>
  <p>Tested like so (with the help of <a href="https://sinonjs.org/how-to/lolex-async-promises/" rel="nofollow noreferrer">this article</a>):</p>
  <pre><code>it('retries after a given delay', function() {
    const clock = sinon.useFakeTimers()
    const promise = ensureCount(2, { delay: 200 })
  
    clock.tick(200)
    // Make some assertions.
  
    clock.tick(200)
    // Make some assertions.
  
    clock.tick(200)
    // Make some assertions.
  
    return promise
  })
  
  </code></pre>
  <p>The expected console output (which is what happens without fake timers):</p>
  <pre><code>Attempt 0
  Attempt 1
  Attempt 2
  ✔ retries after a given delay (405ms)
  </code></pre>
  <p>The actual console output (which happens with fake timers):</p>
  <pre><code>Attempt 0
  Attempt 1
  Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure &quot;done()&quot; is called; if returning a Promise, ensure it resolves.
  </code></pre>
  <p><strong>The Question:</strong></p>
  <p>Is there a way to get the fake timers to apply to every step of the recursive call, rather than just the first one?</p>