Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unhandled async errors crash Jest. #2059

Closed
cpojer opened this issue Nov 6, 2016 · 46 comments
Closed

Unhandled async errors crash Jest. #2059

cpojer opened this issue Nov 6, 2016 · 46 comments

Comments

@cpojer
Copy link
Member

cpojer commented Nov 6, 2016

On master, I changed one of the tests in jest-haste-map from toBeDefined() or something to not.toBeDefined(). It would then go on to crash Jest:

[cpojer: ~/Projects/jest (master)]$ jest "haste-map.*index"

 RUNS  packages/jest-haste-map/src/__tests__/index-test.js

/Users/cpojer/Projects/jest/packages/jest-jasmine2/node_modules/jest-matchers/build/index.js:110
        throw error;
        ^
Error: expect(received).toBeNull()

Expected value to be null, instead received
  undefined
    at HasteMap.hasteMap.once (/Users/cpojer/Projects/jest/packages/jest-haste-map/src/__tests__/index-test.js:685:62)
    at HasteMap.g (events.js:291:16)
    at emitOne (events.js:96:13)
    at HasteMap.emit (events.js:188:7)
    at Timeout.emitChange (/Users/cpojer/Projects/jest/packages/jest-haste-map/src/index.js:562:14)
    at ontimeout (timers.js:365:14)
    at tryOnTimeout (timers.js:237:5)
    at Timer.listOnTimeout (timers.js:207:5)

@DmitriiAbramov what have we done?

@cpojer
Copy link
Member Author

cpojer commented Nov 7, 2016

Oh, it might have been because I didn't return the promise but instead am using Jasmine's async work. Nevertheless, we should hook up an unhandled promise handler in Jest.

@cpojer cpojer changed the title Thrown promises crash Jest Unhandled async errors crash Jest. Nov 29, 2016
@mweststrate
Copy link
Contributor

mweststrate commented Nov 29, 2016

Currently we use in our tests a utility to work around this in a quite cumbersome way:

/**
 * In async tests, JEST will die (in watch mode) if an exception is thrown from a callback. This utility will catch
 * the errors instead and report the test as failed in these case *
 *
 * @param {jest.DoneCallback} done
 * @param {T} callback
 * @returns {T}
 */
export function catchErrors<T extends Function>(done: jest.DoneCallback, callback: T): T {
	return function() {
		try {
			callback.apply(this, arguments)
		} catch (e) {
			done.fail(e)
		}
	} as any as T
}

which then can be used as follows:

describe("suite", () => {
	it("should handle async exceptions", (done) => {
                setTimeout(catchErrors(done, (err, res) => {
                        throw "Catched by catchErrors so that our tests properly fail!"
                        done() 
                }), 100)
        })
})

Any cleaner approach to this would be appreciated!

@mmcgahan
Copy link
Contributor

mmcgahan commented Dec 1, 2016

this sounds somewhat similar to #1873, where done() is unreachable after failing expect calls in Promises

@julien-f
Copy link

Any news on this?

I also have a repro repo here if that can help.

@lucasconstantino
Copy link

This is some huge drawback for me :( Trying to find a way to circumvent this properly...

@theogravity
Copy link

this is quite frustrating as I have no idea where it's dying

@capaj
Copy link
Contributor

capaj commented Jan 24, 2017

@mweststrate this should be in the jest core. Seriously, this has been lying here for two months and no one opened a PR yet? 😖

@cpojer
Copy link
Member Author

cpojer commented Jan 24, 2017

@capaj seems like you are on the hook to make that PR. Jest is an open source project, if you'd like something to be fixed, please start contributing. The attitude you are showing on this issue tracker is not appropriate.

@capaj
Copy link
Contributor

capaj commented Jan 24, 2017

@cpojer sorry I am just very enthusiastic about my favorite OSS tools. I wasn't aware that displaying negative emotions about negative things is prohibited in jest repo. Next time, I will try to write my comments like a robot, deprived of any emotions.

@cpojer
Copy link
Member Author

cpojer commented Jan 24, 2017

I'd prefer if you channeled your enthusiasm into code which will help make this project better for everyone or channel it into productive conversation. Negative comments don't help anybody; if that's the only thing you are contributing to this project I'd prefer to see you using a different testing platform.

@capaj
Copy link
Contributor

capaj commented Jan 24, 2017

@cpojer I beg to disagree, but that's a discussion better suited for some other place/platform

@cpojer
Copy link
Member Author

cpojer commented Jan 24, 2017

That's ok, we can disagree on this but the Jest project doesn't need your negativity and we won't accept this behavior here.

@jeffbski
Copy link

In mocha, the done callback takes an optional error (standard Node.js cb style).

If you call done with a truthy value then it will be used as an error.

promise.then(x => {
  // do something
  done(); // successful
}).catch(err => {
  // do something with error
  done(err); // hand error to test runner
});

@IPWright83
Copy link

Having a look through this there isn't a reproduction example, so I thought I'd include one. In here the first test will fail reporting

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

while the other two tests correctly reporting back the failed expectation. Correctly works in Jasmine.

describe("Error Reporting", function() {

     it("Async", function(done) {
       setTimeout(function() {
          expect(true).toBe(false);
          done();
       }, 100);
    });

    it("Sync", function() {
        expect(true).toBe(false);
    });

    it("Fake Async", function(done) {
        expect(true).toBe(false);
        done();
    });
});

@evansiroky
Copy link

I submitted #1897 that aslo included a reproducible example: https://github.com/evansiroky/jest-exec-bug

evocateur pushed a commit to evocateur/lerna that referenced this issue Mar 20, 2017
Due to jestjs/jest#2059, turns out we need
those try/catch blocks I tried to remove in the previous PR.

Partially reverts lerna#682
evocateur added a commit to lerna/lerna that referenced this issue Mar 20, 2017
Due to jestjs/jest#2059, turns out we need
those try/catch blocks I tried to remove in the previous PR.

Partially reverts #682
@wilomgfx
Copy link

@jeffbski indeed thats the most convenient way of doing this! I thought we would be able
to do the same thing with JEST, but instead we have to do : done.fail(ARG)

dignifiedquire added a commit to dignifiedquire/jest that referenced this issue Aug 15, 2017
dignifiedquire added a commit to dignifiedquire/jest that referenced this issue Aug 16, 2017
@dignifiedquire
Copy link
Contributor

@aaronabramov the PR should be ready now, it would be great to get some review on it so we can get this shipped :)

dignifiedquire added a commit to dignifiedquire/jest that referenced this issue Aug 22, 2017
dignifiedquire added a commit to dignifiedquire/jest that referenced this issue Aug 22, 2017
dignifiedquire added a commit to dignifiedquire/jest that referenced this issue Aug 24, 2017
cpojer pushed a commit that referenced this issue Aug 24, 2017
* wip: start handling async errors

Ref #2059

* Implement basic cancelation

* Improve cancelation

* lint and flow happy, more tests

* snapshot updates

* happy tests

* add tests for before hooks

* log errors if they escape us

* use p-cancelable

* improve based on CR
@cpojer
Copy link
Member Author

cpojer commented Aug 24, 2017

This is part of Jest 21 thanks to @dignifiedquire. Published jest@test (Jest 21 beta) so you can give this a try. Also enjoy a substantially faster Jest startup.

@ron-liu
Copy link

ron-liu commented Sep 25, 2017

@dignifiedquire @cpojer I still got timeout for the following test. I am sure I installed version 21.1.0 and I also tried version 21.0.2.
Did I miss anything ?

test.spec.js

it('exception promise', (done) => {
        setTimeout(()=>{
                expect(true).toEqual(false)
                done()
        }, 10)
})

package.json

{
  "name": "testJest",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "jest": "21.1.0"
  },
  "scripts": {
    "test": "jest --debug"
  }
}

image

@kimjoar
Copy link
Contributor

kimjoar commented Sep 26, 2017

Looks like ^ fails when using jsdom, but not when using the node env.

Using node:

$ npx jest --env node
 FAIL  test/index.test.js
  ● exception promise

    expect(received).toEqual(expected)
    
    Expected value to equal:
      false
    Received:
      true
      
      at Timeout.setTimeout [as _onTimeout] (test/index.test.js:3:18)
      at ontimeout (timers.js:469:11)
      at tryOnTimeout (timers.js:304:5)
      at Timer.listOnTimeout (timers.js:264:5)

  ✕ exception promise (18ms)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        0.216s, estimated 6s
Ran all test suites.

Using jsdom:

$ npx jest --env jsdom
 FAIL  test/index.test.js (5.114s)
  ● exception promise

    Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
      
      at node_modules/jest-jasmine2/build/queue_runner.js:65:21
      at ontimeout (timers.js:469:11)
      at tryOnTimeout (timers.js:304:5)
      at Timer.listOnTimeout (timers.js:264:5)

  ✕ exception promise (5003ms)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        5.733s
Ran all test suites.

Minimal repro: https://github.com/kjbekkelund/jest-timeout-issue-jsdom

@ron-liu
Copy link

ron-liu commented Sep 26, 2017

@kjbekkelund yeah, thank you. --env node solved the issue, I did miss this.
Alos check the jest official help .

@SimenB
Copy link
Member

SimenB commented Dec 6, 2017

I think that last case might be fixed in #4669

@bobrosoft
Copy link

@dignifiedquire hey there. In which Jest version that was fixed? Using Jest 21.1.6 and it's still there. My particular case is there https://stackoverflow.com/a/47760009/5086732, crashing if remove try..catch wrapper from there.

@shdwjk
Copy link

shdwjk commented Jan 10, 2018

I'm still seeing this with v20.0.4. In my case with a check inside a redux store reducer.

@bf
Copy link

bf commented Jan 10, 2018

Seems to be a gift that gives on giving...

@SimenB
Copy link
Member

SimenB commented Jan 10, 2018

Still happening in 22?

@shdwjk
Copy link

shdwjk commented Jan 10, 2018

Ah, is working in 22.0.5. Great, thanks!

@rawroland
Copy link

I am still experiencing this in 22.1.1 in the following test:

it('replies with the correct message': done => {
  // Initialise a bot with the MS botbuilder framework
  bot.on('send', message => {
     expect(message.text).toEqual('Is everything ok?');
     done();
   });
});

@SimenB
Copy link
Member

SimenB commented Jan 16, 2018

Can you provide a repro I can pull down to test?

@rawroland
Copy link

Thanks for the quick reply. Yes, will do so within the next 30 mins.

@rawroland
Copy link

Here is a repo to reproduce the issue: https://github.com/rawroland/async-jest-test.

@SimenB
Copy link
Member

SimenB commented Jan 26, 2018

@rawroland that's expected, you're basically seeing #3917.

I'd recommend using promise instead of callback based code, then you don't have to worry about that sort of code flow. E.g.

it('replies with the correct message', async () => {
  // Initialise a bot with the MS botbuilder framework
  const result = await new Promise(resolve => bot.on('send', resolve));

  expect(result.text).toEqual('Is everything ok?');
});

@rawroland
Copy link

Thank you for the information.

@github-actions
Copy link

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 13, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests