Почему этот тест проваливается только тогда, когда есть отказ?

#javascript #node.js #promise #sinon

Вопрос:

Этот тест проходит; т. е. синон говорит, что заглушка на самом деле называется:

 const sinon = require('sinon')

async function underTest (s){
  promise1 = new Promise((yes, no)=>yes())
  promise2 = new Promise((yes, no)=>yes())

  Promise.all([promise1, promise2]).then(s.yes).catch(s.no)
}

async function test(){
  s = {yes: sinon.stub(), no:sinon.stub()}  
  await underTest(s)
  sinon.assert.called(s.yes)
}

test().then(console.log('done'))
 

Обратите внимание, как я не вернул обещание от Promise.all .

Однако следующий тест не пройдет, и синон скажет, что заглушка НЕ была вызвана:

 const sinon = require('sinon')

async function underTest (s){
  promise1 = new Promise((yes, no)=>no())
  promise2 = new Promise((yes, no)=>no())

  Promise.all([promise1, promise2]).then(s.yes).catch(s.no)
}

async function test(){
  s = {yes: sinon.stub(), no:sinon.stub()}  
  await underTest(s)
  sinon.assert.called(s.no)
}

test().then(console.log('done'))
 

И если я верну Promise.all его , то это пройдет, и синон скажет s.no , что заглушка называется:

 const sinon = require('sinon')

async function underTest (s){
  promise1 = new Promise((yes, no)=>no())
  promise2 = new Promise((yes, no)=>no())

  return Promise.all([promise1, promise2]).then(s.yes).catch(s.no)
}

async function test(){
  s = {yes: sinon.stub(), no:sinon.stub()}  
  await underTest(s)
  sinon.assert.called(s.no)
}

test().then(console.log('done'))
 

Имеет смысл, что тест пройдет только в том случае, если я верну обещание от Promise.all . Если я ничего не верну async , функция разрешится undefined , и заглушка может быть вызвана, а может и не быть.

Мой вопрос в том, что я ожидал бы, что тест провалится, если не будет заявления о возврате, даже в первом случае, когда обещания разрешатся. Я бы ожидал, что синон скажет мне s.yes , что ее не вызывали. Но почему это проходит? Почему существует несоответствие между решением и отклонением?

Ответ №1:

Я запускаю твой код. Нет. Ваш первый тест кода / случая выполнен, но результат не пройден.

У вас есть лучший способ узнать это, если вы также реализуете catch при запуске теста примерно так:

 test()
.then(() => console.log('done'))
.catch((error) => console.log('Error:', error.message));
 

Вы используете асинхронное ожидание непоследовательно.

Если вы используете асинхронное ожидание, вы можете поймать ошибку с помощью try и catch.

Например:

 async function underTest (s){
  promise1 = new Promise((yes, no)=>yes())
  promise2 = new Promise((yes, no)=>yes())

  try {
    await Promise.all([promise1, promise2]);
    s.yes();
  } catch {
    s.no();
  }
  // This will return Promise<void>
}
 

Комментарии:

1. Спасибо, что уделили мне время. Но, как вы можете понять, Синон говорит, что в первом случае это » да » на самом деле называется. в то время как s.no не называется. Должно быть, что не использование await должно привести к сбою в обоих случаях, а не только в одном, верно?

2. Я отредактировал свой ответ после вашего комментария, чтобы добавить пример. Нет. первый случай s.да не называется. Ошибка вывода первого случая в моем терминале: Ошибка: ожидалось, что заглушка была вызвана по крайней мере один раз, но никогда не вызывалась

3. Вау, ты прав, теперь он больше не работает.