8

Using Mocha and chai-as-promised, I'm trying to test that my promised are being resolved and rejected properly. But the expect functions given by chai-as-promised aren't properly causing the tests to fail. Example:

test.js

const chai = require('chai')
chai.use(require('chai-as-promised'))
const expect = chai.expect

describe('foo', () => {
  it('resolve expected', () => {
    expect(new Promise((res,rej) => {res()})).to.be.fulfilled
  })
  it('resolve unexpected', () => {
    expect(new Promise((res,rej) => {res()})).to.be.rejected
  })
  it('reject expected', () => {
    expect(new Promise((res,rej) => {rej()})).to.be.rejected
  })
  it('reject unexpected', () => {
    expect(new Promise((res,rej) => {rej()})).to.be.fulfilled
  })
})

When I execute mocha test.js:

  foo
    ✓ resolve expected
    ✓ resolve unexpected
(node:2659) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): AssertionError: expected promise to be rejected but it was fulfilled with undefined
(node:2659) [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.
    ✓ reject expected
    ✓ reject unexpected
(node:2659) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 4): AssertionError: expected promise to be fulfilled but it was rejected with undefined


  4 passing (10ms)

You can see the assertion-errors seem to get thrown, but mocha doesn't pick them up. How can I get mocha to recognize the failures?

ewok
  • 20,148
  • 51
  • 149
  • 254
  • 2
    I think you're supposed to return the `expect` calls. Have you tried adding the `return` keyword to each test? – Luke Stoward Dec 18 '17 at 16:40
  • 1
    I just gave that a try. It works. But now I wonder how you put multiple `expect` statements into a single test? – ewok Dec 18 '17 at 16:42
  • I'm not sure, I haven't used the chai-promise library in a while. – Luke Stoward Dec 18 '17 at 16:44
  • Could you please accept the solution so others will find the answer easier. Also if you answer your second question, let me know and I can update the solution :) – Luke Stoward Dec 18 '17 at 16:48

3 Answers3

12

As we confirmed, and for future reference, the problem was that you did not return the assertion in each test.

it('reject expected', () => {
  return expect(new Promise((res,rej) => {rej()})).to.be.rejected
})
it('reject unexpected', () => {
  return expect(new Promise((res,rej) => {rej()})).to.be.fulfilled
})

This is why the tests passed but then later printed an "unhandled" promise when it did finally return. The return keyword informs mocha to wait for the async function to resolve/reject.

Luke Stoward
  • 1,480
  • 14
  • 24
2

Alternatively with chai-as-promised library, you can try using chai.should and call .notify to indicate its 'done'. Like this:

const chai = require('chai');
chai.use(require('chai-as-promised'));
chai.should();

const expect = chai.expect;

describe('foo', () => {
    it('resolve expected', () => {
        expect(new Promise((res, rej) => { res(); })).to.be.fulfilled;
    });
    it('resolve unexpected', (done) => {
        // expect(new Promise((res, rej) => { res(); })).to.be.rejected;
        new Promise((res, rej) => { res(); }).should.be.rejected.and.notify(done);
    });
    it('reject expected', (done) => {
        // expect(new Promise((res, rej) => { rej(); })).to.be.rejected;
        new Promise((res, rej) => { rej(); }).should.be.rejected.and.notify(done);
    });
    it('reject unexpected', (done) => {
        // expect(new Promise((res, rej) => { rej(); })).to.be.fulfilled;
        new Promise((res, rej) => { rej(); }).should.be.fulfilled.and.notify(done);
    });
});

This way mocha will recognize the test failure:

foo
    √ resolve expected
    1) resolve unexpected
    √ reject expected
    2) reject unexpected


  2 passing (37ms)   2 failing

  1) foo
       resolve unexpected:
     AssertionError: expected promise to be rejected but it was fulfilled with undefined


  2) foo
       reject unexpected:
     AssertionError: expected promise to be fulfilled but it was rejected with undefined

Check chai-as-promised doc for further reference here

nitya wijayanti
  • 779
  • 7
  • 5
  • 4
    Just return the promise: simpler and cleaner than using `done`. – Louis Dec 19 '17 at 11:52
  • Yeah agree with you @Louis. My suggestion above just to show different style on how to use chai-as-promise, and since ewok asked on how to put several assertions in one test, then it's not possible to use 'return' in such case. Using 'done' may works if we want to put several assertions when testing promise, but I do think we should have separate 'it' to test a specific case. – nitya wijayanti Dec 20 '17 at 02:53
0
 it ('creates images', async () => {
      
      assert.equal(imageCount,1)
      const event = result.logs[0].args
      assert.equal(event.id.toNumber(),imageCount.toNumber(),'id is correct')
      assert.equal(event.hash,hash,'Hash is correct')
      assert.equal(event.description,'Image Description','description is correct')
      assert.equal(event.tipAmount,'0','tip amount is correct')
      assert.equal(event.author, author, 'author is correct')

      await decentragram.uploadImage('','Image description', { from: author }).should.be.rejected;
      await decentragram.uploadImage('Image hash','', { from:author }).should.be.rejected;
    })

facing the same issue here.But agree with [luke-stoward][1]

Solution: Add return

it ('creates images', async () => {
     return
      assert.equal(imageCount,1)
      const event = result.logs[0].args
      assert.equal(event.id.toNumber(),imageCount.toNumber(),'id is correct')
      assert.equal(event.hash,hash,'Hash is correct')
      assert.equal(event.description,'Image Description','description is correct')
      assert.equal(event.tipAmount,'0','tip amount is correct')
      assert.equal(event.author, author, 'author is correct')

      await decentragram.uploadImage('','Image description', { from: author }).should.be.rejected;
      await decentragram.uploadImage('Image hash','', { from:author }).should.be.rejected;
    })
Ahmad Bashir
  • 1
  • 1
  • 3