简体   繁体   中英

How to use async-await and then in one Mocha test with done?

So, I have test like this:

it 'sample test', (done)->
    await Promise.resolve 0
    Promise.resolve 0
    .then ->
        done()
    null

Notice, that null in the end is to avoid returning Promise. However, test falls with classic "Error: Resolution method is overspecified. Specify a callback *or* return a Promise; not both"

I checked result JS code, nothing strange:

it('Sample test', async function(done) {
    await Promise.resolve(0);
    Promise.resolve(0).then(function() {
      return done();
    });
    return null;
});

I don't understand, what is wrong, because (as I think) this code should not return promise. Also, when I wrapped first promise (with await ) into setTimeout , it works fine.

it 'working test', (done)->
    setTimeout ->
        await Promise.resolve 0
    , 0
    Promise.resolve 0
    .then ->
        done()
    null

Of course, with setImmediate instead of setTimeout it works too, so I think, that the cure in this situation is callback. But this is extremely dirty solution. How to mix then , async-await and done in one test more clearly?

Using await in the function body turns the test function into an async function.

async functions always return a Promise .

So in this case:

it('Sample test', async function(done) {
    await Promise.resolve(0);
    Promise.resolve(0).then(function() {
      return done();
    });
    return null;
});

...the test function is returning a Promise that will resolve to null .


In your other example Mocha doesn't complain because the code compiles to this:

it('working test', function(done) {
  setTimeout(async function() {
    return (await Promise.resolve(0));
  }, 0);
  Promise.resolve(0).then(function() {
    return done();
  });
  return null;
});

...since await is now within the body of the function passed to setTimeout .

(Note that the two tests behave very differently ).


There isn't a reason to use both done and an async / await test function (or one that returns a Promise ) so Mocha fails the test with that error.

Your first test can be simplified to this:

it 'sample test', ()->
    await Promise.resolve 0
    await Promise.resolve 0

...or if you need to do work in a then chained to the second Promise you can just do this:

it 'sample test', ()->
    await Promise.resolve 0
    await Promise.resolve 0
    .then ->
        // do stuff here

In Mocha v3.0.0 and newer, returning a Promise and calling done() will result in an exception, as this is generally a mistake - docs

Since async function always return Promise you are getting this error. Possible solutions:

  • Remove async function

     it('Sample test', function(done) { Promise.resolve(0) .then(function() { ... }) .then(function() { ... // if necessary }) .then(function() { done(); }); }); 
  • Return Promise

     it('Sample test', function() { return Promise.resolve(0) .then(function() { ... }) .then(function() { ... // if necessary }); }); 
  • Use async/await

     it('Sample test', async function() { await Promise.resolve(0); await Promise.resolve(0); }); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM