Как структурировать тесты для асинхронных функций?

Я привык писать тесты Mocha с использованием стандартной библиотеки NodeJs утверждать, например:

describe('Some module', () => {
   var result = someCall();
   it('Should <something>', () => {
      assert.ok(...);
   });
})

но теперь мой вызов возвращает обещание... поэтому я хочу написать:

describe('Some module', async () => {
   var result = await someCall();
   it('Should <something>', () => {
      assert.ok(...);
   });
})

но это не работает. Мои тесты вообще не запускаются. Любопытно,

describe('Some module', async () => {
   it('Should <something>', () => {
      var result = await someCall();
      assert.ok(...);
   });
})

работает нормально, но проблема в том, что я хочу сделать один вызов и запустить много тестов для него, поэтому я хочу сделать вызов вне вызовов it()

Как заставить это работать?

и пожалуйста не рекомендуют Chai. Я хочу использовать стандартную библиотеку утверждений

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
5
0
540
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Хотя использование немного нетрадиционно, одним из подходов может быть использование before() крючок для достижения того, что вам нужно.

Хук before() предоставит средство вызова функциональности (т.е. someCall()) перед остальными тестами в вашем наборе. Сам хук поддерживает выполнение асинхронной функциональности через функцию обратного вызова (например, done), которую можно вызвать после завершения асинхронной функциональности:

before((done) => {
  asyncCall().then(() => {
    /* Signal to the framework that async call has completed */
    done(); 
  });
});

Один из способов интегрировать это с вашим существующим кодом может быть следующим:

describe("Some module", () => {
  /* Stores result of async call for subsequent verification in tests */
  var result;

  /* User before hook to run someCall() once for this suite, and
  call done() when async call has completed */
  before((done) => {
    someCall().then((resolvedValue) => {
      result = resolvedValue;
      done();
    });
  });

  it("Should <something>", () => {

    /* result variable now has resolved value ready for verification */
    console.info(result);
  });
});

надеюсь, это поможет

Вам не нужно использовать done в before, если asyncCall возвращает Promise. Просто верните Promise. before(() => { return asyncCall().then(() => { // do some stuff before moving to it }); }); Кроме этого +1, я бы тоже использовал before.

nicholaswmin 19.03.2019 08:10

@NikKyriakides спасибо за отзыв :-) Изначально я выбрал подход, основанный на async/await, о котором вы упомянули, однако он, похоже, не работает в моей среде (хотя должен был работать), тогда как опубликованное решение сработало. Есть идеи, почему это может быть?

Dacre Denny 19.03.2019 08:20

Да, вам нужно вернуть Обещание, если вы не используете done. Поскольку функции async уже возвращают Promise, достаточно просто вернуть asyncCall в before. В этом блоке нет необходимости использовать async/await.

nicholaswmin 19.03.2019 11:07

Странно - именно это я и делал изначально. Возможно, завтра мне придется пересмотреть код на моей другой рабочей станции. Спасибо еще раз :)

Dacre Denny 19.03.2019 11:10
Ответ принят как подходящий

before принимает функцию async, поэтому вы можете получить result до запуска тестов и использовать ее в своих тестах следующим образом:

const assert = require('assert');

const someCall = () => Promise.resolve('hi');

describe('Some module', () => {
  let result;

  before(async () => {
    result = await someCall();
  });

  it('Should <something>', () => {
    assert.equal(result, 'hi');  // Success!
  });
});

Mocha уже поддерживает то, что вы хотите сделать.

Функция Mocha describe не предназначена для асинхронной работы. Однако функция it предназначена для асинхронной работы либо путем передачи обратного вызова done (фактическое имя параметра может быть любым, например «complete», «resolve» или «done»), либо путем возврата обещания, либо путем передачи функции async.

Это означает, что ваш тест почти правильный. Вам просто нужно сделать это вместо этого:

describe('Some module', () => {
   it('Should <something>', async () => {
      var result = await someCall();
      assert.ok(...);
   });
})

Если вам нужно запустить функцию someCall() один раз для нескольких блоков it, вы можете сделать, как указано в других ответах, и вызвать ее в блоке before.

Другие вопросы по теме