Search code examples
javascriptunit-testingassertes6-promise

Making assertions with catch in promises exceeds timeout


I want to make an assertion in a catch block of a promise chain, but it reaches the timeout. Assertions work in then blocks, but it seems in the catch block, done() is never reached. Is it being suppressed? Is there a better way to test promise rejections?

import assert from 'assert';
import { apicall } from '../lib/remoteapi';

describe('API calls', function () {
  it('should test remote api calls', function (done) {
    apicall([])
      .then((data) => {
        assert.equal(data.items.length, 2); // this works fine
        done();
      })
      .catch((e) => {
        console.log('e', e);
        assert.equal(e, 'empty array'); // ? 
        done(); // not reached?
      });
  });
});

The promise rejection

apicall(channelIds) {
  if(channelIds.length === 0) return Promise.reject('empty array');

  ...        

}

I get this error:

Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.

Solution

  • If this is mocha and you're using Promises, don't use the callback functionality; it makes things very awkward as you're discovering. Instead, mocha lets you return the promise in your test. A rejected Promise means a failed test, and a successful Promise means a succeeding test. A failed assertion causes the code to throw an exception, which will automatically fail the Promise, which is usually what you'll want. In short:

    describe('API calls', function () {
      it('should test remote api calls', function () {
        return apicall([])
          .then((data) => {
            assert.equal(data.items.length, 2);
          });
      });
    });