4

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?

1 Answer 1

5

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).

Sign up to request clarification or add additional context in comments.

4 Comments

Gotcha, thanks for the explanation! I didn't realize that async functions returned Promises. In my test I'm actually doing something like await thisMethod();setTimeout(1000,done);. Here I'm mixing and matching promises and callbacks; I guess the only wait to get this to work is to wrap the entire thing in a Promise.
@NickManning No you don't :). async functions already return a Promise. Look at my practical example.
The problem is that I'm not able to mix and match async/await and callbacks, without what feels like a workaround. My use case is that my test contains two lines: the first line is await myFunc(); and the second line is a function that takes a callback. The test is finished when the callback of the second line is called. I have two choices: not use await, or wrap everything in a Promise. I tried to show what I mean here: codesandbox.io/s/w78x85wl98
Ah, I get it. I'd personally wrap the callback-style function in a Promise so I can use async/await on everything. As I said you can await both Promise and async functions the same. In general, 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).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.