Jest: Promises break after importing react-native

Created on 21 Sep 2016  ·  5Comments  ·  Source: facebook/jest

Issue Description

A Jest test using Promise will time out if react-native has been imported or required at any point before the test runs.

Output:

> jest

 PASS  __tests__/withoutReactNative.js
  Without React Native
    ✓ works with promises (5ms)

 FAIL  __tests__/withReactNative.js (5.465s)
  With React Native
    ✕ no longer works (5009ms)

  ● With React Native › no longer works

    Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.

      at tryOnTimeout (timers.js:232:11)
      at Timer.listOnTimeout (timers.js:202:5)

Steps to Reproduce / Code Snippets

Option A: Example project

https://github.com/cooperka/jest-broken-promises

Option B: Create from scratch

  1. react-native init ProjectName
  2. Follow http://facebook.github.io/jest/docs/tutorial-react-native.html
  3. Add a test that uses Promise

    • The test should work just fine

  4. import or require React Native before your test

    • The test will no longer work

      Workaround


@nyura123 suggested a workaround that's fairly effective, but it makes things messy and may not work for all use-cases (e.g. when using jest.useFakeTimers() or RN's NetInfo.isConnected.fetch()). See the workaround in action here.

Additional Information

I'm submitting this issue in order to re-examine https://github.com/facebook/react-native/issues/6104 as suggested by @cpojer. It seems to be a compatibility issue between Jest and React Native, though it's not clear which project a fix should be made in.

Most helpful comment

I'm also encountering this (Jest 16.0.1):

This passes:

it('foo', async () => {
  await Promise.resolve();
  expect(1).toEqual(1);
});

This times out:

import 'react-native';
it('foo', async () => {
  await Promise.resolve();
  expect(1).toEqual(1);
});

Another simpler workaround is to re-set Promise immediately before the async test cases run

beforeAll(() => {
  global.Promise = require.requireActual('promise');
});

it('does something async', ...

All 5 comments

I'm also encountering this (Jest 16.0.1):

This passes:

it('foo', async () => {
  await Promise.resolve();
  expect(1).toEqual(1);
});

This times out:

import 'react-native';
it('foo', async () => {
  await Promise.resolve();
  expect(1).toEqual(1);
});

Another simpler workaround is to re-set Promise immediately before the async test cases run

beforeAll(() => {
  global.Promise = require.requireActual('promise');
});

it('does something async', ...

Thanks for that @stevehollaar! It's a much nicer workaround but unfortunately it doesn't fix timers (you can try it on my demo project if you like, I've updated the code). The issue still exists in Jest 16.

Just waisted the better part of a day on this. Thanks for posting a workaround.

Update: There's now a section for this issue in the docs. It seems to be a known issue but probably won't be fixed any time soon. You can use any of the 3 workarounds here to resolve it (mine, Steve's, or the doc's); they all do pretty much the same thing.

I ran into a similar issue, without react-native, when my promise was wrapped in an expect().not.toThrow().

In a nutshell, failed expectations are swallowed in this scenario, and execution of the test stops on the failed line. Since the test never makes it to the end, you get the async timeout error.

Documenting here in case others have similar (non-react-native) experience.

Was this page helpful?
0 / 5 - 0 ratings