-
Notifications
You must be signed in to change notification settings - Fork 108
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 rejection warnings when expecting a rejection #173
Comments
This is a bug introduced in Node.js v7.0.0. I can only recommend not using v7 for now. See nodejs/node#8217. |
I am also experiencing this issue on Node
This spec should fail: import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
chai.use(chaiAsPromised);
const expect = chai.expect;
describe('Test', () => {
it('should fail', () => {
expect(Promise.resolve(2)).to.eventually.equal(1);
});
}); Instead, the output is:
And the process exits with a 0 exit code. |
Ugh, it does seem this kind of major change slipped in to Node.js 6.x as well, although that bug thread is confusing :(. |
@darkobits I think you need to return the expect
Also I think my (OP) problem was that I was using chai v4, I tested it again and the original test lib works well with chai 3.5 |
@laggingreflex do you think this might be a regression in chai v4? If so please please do file a report on the chai issue tracker 😄 |
Also might wanna check out #157. However, I submitted that a long time ago and there have been a lot of changes since then; it may need further updating. |
Is this still considered a const chai = require('chai');
chai.use(require("chai-as-promised"));
const assert = chai.assert;
describe('rejection assertion', function(){
it('should correctly fail the test', function(){
const p = Promise.resolve("resolved")
return assert.isRejected(p)
})
}) The above erroneously passes:
"chai": "^4.0.1",
"chai-as-promised": "^6.0.0",
"mocha": "^3.4.2" |
I'm having exactly the same issue right there version: Source Code:export default class SomeManager {
/**
* @param {SomeOtherManager} someOtherManager
*/
constructor(someOtherManager) {
this._someOtherManager = someOtherManager;
}
/**
* @return {Promise}
*/
execute() {
return this._someOtherManager.get('id');
}
} Spec file:import chai from 'chai';
import cp from 'chai-as-promised';
import SomeManager from './../../lib/manager/someManager';
import SomeOtherManager from './../../lib/manager/someOtherManager';
import {beforeEach, describe, it} from 'mocha';
import sinon from 'sinon';
describe('SomeManager', () => {
chai.use(cp);
let expect = chai.expect;
let someManager;
let someOtherManagerMock;
beforeEach(() => {
someOtherManagerMock = sinon.createStubInstance(SomeOtherManager);
someManager = new SomeManager(someOtherManagerMock);
});
describe('execute', () => {
it('should reject promise', () => {
// Arrange.
someOtherManagerMock.get.withArgs('id').returns(Promise.reject());
// Act.
let actual = someManager.execute();
// Assert.
return expect(actual).to.eventually.be.resolved;
});
});
}); Output:
With node:
|
@zazoomauro In your case, the problem is that |
@meeber Thanks! |
I also have the same problem |
Have the same issue. process.on('unhandledRejection', () => {}); |
Same here: node: v6.9.1 @vitalets, I think this is not a solution but rather a hack to hide the warning. But it can work in case someone wants to avoid pull request issues :) Edit: I now think the issue is with the 3rd party library I'm using (aws-sdk-mock module). All tests pass as expected, but this warning makes me wonder if I understand correctly the promise feature. I noticed that passing an error argument to the callback in the test like this:
And the piece of code I test:
Behaves very strangely when I reject the promise in the code I test. When I reject it with provided error argument ('Some error' of the callback) then it shows the warning but with the 'Some error' message and not with the "Other error message" that I rejected in the tested code (by the way my test catches the "Other error message" message correctly). If I have time in the weekend, I may look at the code of 'aws-sdk-mock' to confirm the issue (and hopefully to provide a quick fix). |
There are multiple issues brought up by people in this thread. Some of the issues were resolved with the release of Consider the OP's original example with a const chai = require( 'chai' );
const promised = require( 'chai-as-promised' );
chai.use( promised );
chai.should();
const somePromise = new Promise( () => {
throw new Error( 'rejected' );
} );
describe( 'promise', () => {
it( 'should be rejected', () => {
console.log("NOOOOOOOOOOOOO WHYYYYYYYYYYYYYYYY");
return somePromise.should.be.rejected;
} );
} ); Output:
An I don't have time to dig deeper, but this suggests to me that Mocha is introducing at least a one tick delay before |
return the expect worked for me. And when I think about, it makes sense. |
Pseudo-cross-posting idea from mochajs/mocha#3009 (comment) I have something of a workaround for #173 (comment) const chai = require( 'chai' );
const promised = require( 'chai-as-promised' );
chai.use( promised );
chai.should();
const makeSomePromise = () => new Promise( () => {
throw new Error( 'rejected' );
} );
describe( 'promise', () => {
it( 'should be rejected', () => {
return makeSomePromise().should.eventually.be.rejected; // note the addition of `.eventually`
} );
} ); One thing to be aware of, although I think this is inherent to promises' eagerness and error handling design and will be relevant no matter whether Mocha is changed to have no tick delays*, is that if you recreate the promise on a per-test basis then every test must handle its rejection (even if it isn't relevant, e.g. if you're testing that it starts off pending), while on the other hand if you were to reuse a rejected promise in multiple tests then the first test must handle the rejection and once it does so there will be no warning if any subsequent test fails to do so even if it needs to (in other words, even if Mocha allowed you to assign a promise once and use it in multiple tests, it'd be almost equivalent to assigning the promise and immediately calling *(NOTE: In this example any asynchronous test or hook can introduce a delay between the variable assignment outside of any test or hook and actually getting to run this test; you would have to move that variable assignment into a |
Return expect won't sovle the problem, the test can not pass still, and I think this is an upstream problem, cuz it happens on assert package built in Node, maybe mocha.
Here it complains obj is undefined, but it is logged to console successfully. |
Seeing this with Node 6.10.2 and Mocha 3.5.3. Has anybody found a reasonable fix/workaround? My tests cases are of the following form:
|
@hiranya911 It looks to me like something else might be going on in your example than what is being discussed here. For example, I just tested this standalone example that's based on your example, and it works: function methodThatTriggersRejection () {
return Promise.reject(TypeError('testing'));
}
it('should throw for unexpected HTTP errors', () => {
return expect(methodThatTriggersRejection())
.to.be.rejectedWith(TypeError, 'testing');
}); Are you sure that |
It has a promise chain whose
Edit: I just tried returning the exception wrapped in promise rejection as follows.
The tests still passed, and I still got the warnings.
|
@hiranya911 Does the example I provided work without warnings if you copy/paste it into your current project? If not, does it still display warnings if you copy/paste it into an empty project? I suspect you'll need to produce a standalone, reproducible example for us to be able to assist further. Something is causing an extra tick of the event loop to occur between your promise being rejected and it being "handled" by chai-as-promised. However, based on the examples you've provided so far, it doesn't look to be the same issue as discussed in this thread. The issue being discussed in this thread is that when a promise is rejected outside of the |
@meeber I think I've narrowed it down a bit. I'm using
|
@meeber I think I'm running into the issue described here... http://clarkdave.net/2016/09/node-v6-6-and-asynchronously-handled-promise-rejections/ Solution would be to use |
@hiranya911 Thanks! that worked for me. Another alternative is to use callsFake() instead of returns() to return the rejected promise from the stub. Also, it looks like the latest sinon version includes the rejects/returns functions. |
i encountered same issue but was able to resolve this by using async/await like below.
originally i had it like below. which threw rejection when element not found. but cucumber test passed without catching that error.
|
With async/await you don't need chai-as-promised at all: expect(await medProfile.allergiesSection.getTagName()).to.equal('div'); |
I think the major issue here is the bad documentation of All of these pass without an unhandled promise rejection warning and without any expect(Promise.reject).to.be.rejected
expect(Promise.reject).to.be.rejectedWith(YourError)
expect(Promise.reject).to.eventually.rejectedWith(Error).with.property('name', 'YourError')
expect(Promise.reject).to.be.rejectedWith(Error).eventually.with.property('name', 'YourError') but this shows warnings even with expect(Promise.reject).to.eventually.throw(Error) |
Still having this issue, behaving randomly, this always works it('handles message error', (done) => {
const error = new Error('Solver internal error');
producerRPC.sendPayload(consumerHost, {} as any).catch((err) => {
expect(err).to.be.equal(error);
});
}); While this does not describe('sendPayload.robust', () => {
it('handles message error', async () => {
const error = new Error('Solver internal error');
return producerRPC.sendPayload(consumerHost, {} as any).should.eventually.be.rejectedWith(error);
});
}); Sometimes I see |
I'm not using Bluebird but similarly to this thread I'm getting the same warning errors of unhanded rejection when actually expecting a rejection.
Here's a repo to reproduce: https://github.com/laggingreflex/chai-as-promised-reject-test
It was mentioned chai-as-promised is indeed handling the errors (here) but I think they're not being handled soon enough. Putting a console.log there shows that it reaches that code only after the warning has been displayed:
The text was updated successfully, but these errors were encountered: