Как использовать async-await, а затем в одном тесте Mocha с done?

#javascript #async-await #coffeescript #mocha.js #es6-promise

#javascript #async-await #coffeescript #mocha.js #es6-обещание

Вопрос:

Итак, у меня есть такой тест:

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

Обратите внимание, что null в конце концов, чтобы избежать возврата Promise.
Однако тест падает с классическим "Error: Resolution method is overspecified. Specify a callback *or* return a Promise; not both"

Я проверил результат JS-кода, ничего странного:

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

Я не понимаю, что не так, потому что (как я думаю) этот код не должен возвращать обещание.
Кроме того, когда я завернул первое обещание (с await помощью) в setTimeout , оно работает нормально.

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

Конечно, с setImmediate вместо setTimeout этого тоже работает, поэтому я думаю, что лекарство в этой ситуации — обратный вызов. Но это чрезвычайно грязное решение.
Как более четко смешать then , async-await и done в одном тесте?

Ответ №1:

Использование await в теле функции превращает тестовую функцию в async функцию.

async функции всегда возвращают Promise .

Итак, в этом случае:

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

…тестовая функция возвращает a, Promise который разрешит null .


В вашем другом примере Mocha не жалуется, потому что код компилируется в этот:

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

…поскольку await теперь находится в теле функции, переданной setTimeout .

(Обратите внимание, что два теста ведут себя очень по-разному).


Нет причин использовать обе done и async / await тестовую функцию (или ту, которая возвращает Promise ), поэтому Mocha завершает тест с этой ошибкой.

Ваш первый тест может быть упрощен до этого:

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

… или, если вам нужно выполнить работу в then привязке ко второму Promise , вы можете просто сделать это:

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

Ответ №2:

В Mocha версии v3.0.0 и новее возврат обещания и вызов done() приведут к исключению, поскольку это обычно ошибка — документы

Поскольку async function всегда возвращается Promise , вы получаете эту ошибку. Возможные решения:

  • Удалить async function

     it('Sample test', function(done) {
        Promise.resolve(0)
            .then(function() {
                ...
            })
            .then(function() {
                ... // if necessary
            }) 
            .then(function() {
                done();
            });
    });
      
  • Возврат Promise

     it('Sample test', function() {
        return Promise.resolve(0)
            .then(function() {
                ...
            })
            .then(function() {
                ... // if necessary
            });
    });
      
  • Использовать async/await

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