Jest: expect().toBe() crashes silently when failing called from an async callback

Created on 8 May 2017  路  5Comments  路  Source: facebook/jest

using jest 20.0.0, the following test crashes silently on the expect().toBe() and thus fails to call done() so it ends up hitting the jasmine default timeout. If you put a try/catch around the expect().toBe() line you can see that the error it crashes on (and fails to print) is that it cannot compare undefined to "hello" because they have different types. Also note that if you uncomment line 6 and comment out the setTimeout() line, effectively converting the asynchronous callback into a synchronous callback; then jest correctly prints the error immediately and doesn't hit the timeout. I'm expecting jest to properly report the error, even for the asynchronous callback case.

const isCurrentlyBuggy = true;

function sometimesBuggyFunc(callback) {
  if (isCurrentlyBuggy) {
    // If callback is invoked synchronously jest correctly reports: undefined != 'foo'
    //callback(undefined);

    // If callback if invoked asynchronously jest crashes silently on the
    // expect().toBe() and thus never calls done() causing the test case
    // to hang until jasmine default timeout is reached.
    setTimeout(() => callback(undefined), 0);
  } else {
    callback('hello');
  }
}

test.only('the thing', done => {
  expect.assertions(1);
  sometimesBuggyFunc(actual => {
    expect(actual).toBe('foo');
    done();
  });
});

Most helpful comment

@mo I just ran into this as well. I ended up making myself a little helper function:

function makeCallback(done, body) {
  return (...args) => {
    try {
      body(...args);
      done();
    } catch (error) {
      done.fail(error);
    }
  };
}

Using this, you'd replace your code above with:

sometimesBuggyFunc(makeCallback(done, actual => {
  expect(actual).toBe('foo');
}));

All 5 comments

You need to catch the error and call done.fail(). This is how it works :(
However this is not an issue, if you're returning a promise from test.
See docs on that: http://facebook.github.io/jest/docs/en/asynchronous.html#promises

@mo I just ran into this as well. I ended up making myself a little helper function:

function makeCallback(done, body) {
  return (...args) => {
    try {
      body(...args);
      done();
    } catch (error) {
      done.fail(error);
    }
  };
}

Using this, you'd replace your code above with:

sometimesBuggyFunc(makeCallback(done, actual => {
  expect(actual).toBe('foo');
}));

I get this error when running any test marked as async.
eg if I run:
it('this test times out without telling me why', async () => { expect(1).toBe(2); });
I get the following failure:

Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.

  102 | function createdPatchedSpec(OriginalSpec, registry) {
  103 |   function PatchedSpec(attrs) {
> 104 |     OriginalSpec.apply(this, arguments);
      |                  ^
  105 |     if (attrs && attrs.id) {
  106 |       registry[attrs.id] = this;
  107 |     }

I'm running jest 24.1

I get this error when running any test marked as async.
```
I'm running jest 24.1

Same

Can you open up a new issue with a reproduction?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

samzhang111 picture samzhang111  路  3Comments

hramos picture hramos  路  3Comments

jardakotesovec picture jardakotesovec  路  3Comments

Antho2407 picture Antho2407  路  3Comments

Secretmapper picture Secretmapper  路  3Comments