Nick Manning
Nick Manning

Reputation: 2989

Testing mixed async/Promise-based code and callback-based code

This code:

it('should not say overspecified', async function (done) {
    await new Promise(resolve => resolve());
    done();
});

Causes this:Error: Resolution method is overspecified. Specify a callback *or* return a Promise; not both.

But...I'm not returning a Promise. I'm simply awaiting a promise.

If I change my code to this, it works:

it('should not say overspecified',function(){
  return new Promise(async resolve=>{
    await (new Promise(resolve=>resolve()));
    resolve();
  })
});

Why does it only work when I unnecessarily wrap my code in a Promise?

Upvotes: 4

Views: 3664

Answers (1)

nicholaswmin
nicholaswmin

Reputation: 22979

This code:

it('should not say overspecified', async function (done) {
    await new Promise(resolve => resolve());
    done();
});

Causes this: Error: Resolution method is overspecified. Specify a callback or return a Promise; not both.

Because async functions always return a Promise, by design.

In Mocha, you can either return a Promise or use done, but not both.

I'd do it like this:

// Do not pass `done` as a parameter to `it` callback.
it('should not say over specified', function() {
  return new Promise(resolve => resolve())
});

or if you want to use await:

// Do not pass `done` as a parameter to `it` callback.
it('should not say overspecified', async function () {
  await new Promise(resolve => resolve());
});

Here's a practical async/await example:

require('chai').should()

const getFoo = async () => 'foo'

describe('#getFoo()', () =>  {
  it('returns foo', async () => {
    const foo = await getFoo()
    foo.should.equal('foo')
  })
})

You should use done only for callback-based or event-based code.

It's completely unnecessary to use it with Promise-based code such as regular Promises or async/await.

Testing mixed Promise and callback based code:

If I have control over the code that I'm testing (I wrote it), I "promisify" all callback based code I use from external callback-style API's, so the entire asynchronous API of the code I'm working with always uses Promises. If sensibly used, then it obviously makes testing easier as well (by eliminating completely the need for done).

Upvotes: 5

Related Questions