title: Jest fake timers with promises
body: <p>I'm having a little trouble getting the Jest testing framework (version 23.2.0) to work nicely when using a combination of fake timers and promises. Where am I going wrong?</p>
  
  <p>Let's say I have the following module:</p>
  
  <pre><code>// timing.js
  
  export const timeout = ms =&gt;
    new Promise(resolve =&gt; {
      setTimeout(resolve, ms)
    })
  </code></pre>
  
  <p>And my test file looks like:</p>
  
  <pre><code>// timing.test.js
  
  import { timeout } from './timing'
  
  describe('timeout()', () =&gt; {
    beforeEach(() =&gt; {
      jest.useFakeTimers()
    })
  
    it('resolves in a given amount of time', () =&gt; {
      const spy = jest.fn()
  
      timeout(100).then(spy)
      expect(spy).not.toHaveBeenCalled()
  
      jest.advanceTimersByTime(100)
      expect(spy).toHaveBeenCalled()
    })
  })
  </code></pre>
  
  <p>This fails with the following output:</p>
  
  <pre><code>● timeout › resolves in a given amount of time
  
  expect(jest.fn()).toHaveBeenCalled()
  
  Expected mock function to have been called, but it was not called.
  
    15 |
    16 |     jest.advanceTimersByTime(100)
  &gt; 17 |     expect(spy).toHaveBeenCalled()
       |                 ^
    18 |   })
    19 | })
    20 |
  
    at Object.&lt;anonymous&gt; (src/timing.test.js:17:17)
  </code></pre>
  
  <p>However, if I remove the promise:</p>
  
  <pre><code>// timing.js
  export const timeout = ms =&gt; ({
    then: resolve =&gt; {
      setTimeout(resolve, ms)
    }
  })
  </code></pre>
  
  <p>... the test will pass</p>
  
  <pre><code>timeout
    ✓ resolves in a given amount of time (5ms)
  
  Test Suites: 1 passed, 1 total
  Tests:       1 passed, 1 total
  Snapshots:   0 total
  Time:        1.304s
  </code></pre>
  
  <p><strong>UPDATE</strong></p>
  
  <p>Although it's not the most elegant solution, I'm currently using the below test instead. It works, but I'm still intrigued why the original one didn't</p>
  
  <pre><code>import { timeout } from './timing'
  
  describe('timeout', () =&gt; {
    it('resolves in a given amount of time', done =&gt; {
      setTimeout(() =&gt; done(new Error('it didn\'t resolve or took longer than expected')), 10)
      return timeout(9).then(done)
    })
  })
  </code></pre>