jest: "DeprecationWarning: Unhandled promise rejections are deprecated"

This might be the same issue as https://github.com/facebook/jest/issues/3251 but I’m not sure so posting it separately.

With Jest 22.0.6, no config, this test:

test("I'm asynchronous", async () => {
  const promise = Promise.reject("boom!")
  expect("some precondition").toBeFalsy()
  await rejected(promise)
  expect("some postcondition").toBeTruthy()
})

async function rejected(promise) {
  try {
      await promise
  } catch (e) {
      return e
  }
  throw new Error('Expected promise to be rejected')
}

(taken from an unrelated CRA issue)

produces this log:

(node:33041) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): boom!
(node:33041) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
 FAIL  ./test.js
  ✕ I'm asynchronous (6ms)

  ● I'm asynchronous

    expect(received).toBeFalsy()
    
    Expected value to be falsy, instead received
      "some precondition"

      2 |   const promise = Promise.reject("boom!")
      3 | 
    > 4 |   expect("some precondition").toBeFalsy()
      5 | 
      6 |   await rejected(promise)
      7 | 
      
      at Object.<anonymous>.test (test.js:4:31)

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

Note these two lines:

(node:33041) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): boom!
(node:33041) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

The first line is being discussed in https://github.com/facebook/jest/issues/3251 with a feature request of making the logging configurable. (There is also a separate report in https://github.com/facebook/jest/issues/3251#issuecomment-337032314 of catch() failing to attach error handlers when it’s too late.)

But I’m worried about the second line. Does it mean that when Node changes behavior as it advertises in the deprecation warning, all tests that print this message will start crashing the process? Or can I safely ignore the warning without worrying that my test suite will be very painful to upgrade to future Node versions when the behavior is flipped? Is there anything Jest should be doing to safeguard my test suite from crashing the test runner in the future, and is this a valid concern at all?

I’m using Node 8.9.1 on macOS Sierra.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 38
  • Comments: 25 (5 by maintainers)

Commits related to this issue

Most upvoted comments

any update on this?

Does it mean that when Node changes behavior as it advertises in the deprecation warning, all tests that print this message will start crashing the process?

Wouldn’t you want a UnhandledPromiseRejectionWarning to be treated as a test failure?

In a previous project using Mocha, I set up make-promises-safe to fail the build when promise rejections weren’t being caught. Unfortunately I haven’t yet figured out how to get that working with Jest, likely because Jest has its own handler for promise rejections.

Personally I dislike seeing warnings like this with no line numbers to go resolve the issues – and because it doesn’t fail the build, a bug could have been introduced long ago without noticing. Is there any way to make this better?

(node:31851) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'account' of undefined
(node:31851) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:31851) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Hope this will help you to understand the scene.

https://spion.github.io/posts/why-i-am-switching-to-promises.html

jest 24.1.0, similar deprecation warning in unit test

[Received promise resolved instead of rejected
Resolved to value: {"cell": "1234567890", "customer_id": 1, "email": "home@yahoo.com",   "  expire_datetime": "2019-02-19T19:12:51.908Z", "fort_token": "12349596874567678906", "name": "", "role": "admin"}
(node:13136) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated     either by throwing inside of an async function without a catch block, or by rejecting a promise which was   not handled with .catch(). (rejection id: 6)
(node:13136) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the   future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
(node:13136) UnhandledPromiseRejectionWarning: Error: expect(received).rejects.toThrow()](url)

D:\ANGUALRJS2 PROJECTS\PR02>ngh An error occurred!

(node:4020) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: Unspecified error (run without silent option for detail) (node:4020) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

I noticed something that I believe might be related to this. I ejected from create-react-app to get to the testing scripts.

// Makes the script crash on unhandled rejections instead of silently
// ignoring them. In the future, promise rejections that are not handled will
// terminate the Node.js process with a non-zero exit code.
process.on('unhandledRejection', err => {
  throw err;
});

That works and exits the test suite if I add a promise rejection into a test. When I upgrade Jest from 20.0.4 -> ^22.1.4 the promise warning is displayed and test suite successfully goes into watch mode. I would think jest would still fail as in the older version that CRA has.

Ouch, this is forcing me to put

return Promise.reject(...);

in my application code… not sure what to do

if you try to debug this:

it(`should not produce unhandled Errors`, async () => {
            async function rejected(throwMethod: 'reject' | 'throw' | null) {
                try {
                    if (throwMethod === 'reject') {
                        return Promise.reject(Error('error from Promise.reject'));
                    }
                    if (throwMethod === 'throw') {
                        throw Error('error from throw');
                    }
                    return await fetch('hello');
                } catch (e) {
                    throw e;
                }
            }

            try {
                await rejected('reject');
            } catch (error) {
                console.log(error);
                expect(error).toHaveProperty('message', 'error from Promise.reject');
            }

            try {
                await rejected('throw');
            } catch (error) {
                console.log(error);
                expect(error).toHaveProperty('message', 'error from throw');
            }
        });

you get an unhandled error that’s coming from throw Error('error from throw');, but the JavaScript code is perfectly valid, if you paste this in Chrome’s console:

(async () => {
            async function rejected(throwMethod) {
                try {
                    if (throwMethod === 'reject') {
                        return Promise.reject(Error('error from Promise.reject'));
                    }
                    if (throwMethod === 'throw') {
                        throw Error('error from throw');
                    }
                    return await fetch('hello');
                } catch (e) {
                    throw e;
                }
            }

            try {
                await rejected('reject');
            } catch (error) {
                console.log(error);
            }

            try {
                await rejected('throw');
            } catch (error) {
                console.log(error);
            }
        })()

you get a console log of the two error, with no Unhandled

I think the issue here is that we clean up our unhandledRejection handler when the test exits, which means this error bubbles up all the way to node.

Not sure how to best handle it. I think maybe @aaronabramov’s original suggestion in https://github.com/facebook/jest/issues/3251#issuecomment-292677892

Or we could try to be smarter about attaching and detaching the listener, similar to how you solved #4767.

Came across this too, wasn’t able to work around it so having to abandon Jest for now 😦

There’s an article on Medium covering those node warnings:

https://medium.com/dailyjs/how-to-prevent-your-node-js-process-from-crashing-5d40247b8ab2

Just made those changes on my main fetch and those warnings were gone from tests

return window.fetch(api.API_PUBLIC + endpoint + queryString, {
        method,
        headers: new Headers({
            Accept: 'application/json',
            'Content-Type': 'application/json',
            AppKey: api.APP_KEY,
            ...headers,
        }),
        ...bodyString,
    }).then(response => response.json()).then(data => {
        if (data.error) {
            return process.on('unhandledRejection', (reason, promise) => {
                promise.reject(data.error);
            });
        }

        return Promise.resolve(data);
    }).catch(error => process.on('unhandledRejection', (reason, promise) => {
        promise.reject(typeof error === 'string' ? error : error.message);
    }));

Same issue throwing an error asynchronously, see #5911 for a reproduction

I don’t think our intention was to exit the test suite btw (that sounds pretty annoying).

The only reason we added that line is to make sure errors in our scripts (not in the actual tests!) crash early.

(node:8040) [DEP0018] DeprecationWarning: Unhandled promise rejections are depre cated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.