Как указать точный порядок выполнения асинхронных вызовов в модульных тестах Scala? - PullRequest
0 голосов
/ 23 сентября 2018

Я написал много разных модульных тестов для фьючерсов в Scala.Все асинхронные вызовы используют контекст выполнения.Чтобы убедиться, что асинхронные вызовы всегда выполняются в одном и том же порядке, мне нужно отложить некоторые задачи, что довольно сложно и замедляет тестирование.Исполнитель может по-прежнему (в зависимости от своей реализации) выполнять некоторые задачи раньше других.

Каков наилучший способ проверки параллельного кода с определенным порядком выполнения?Например, у меня есть следующий тестовый пример:

"firstSucc" should "complete the final future with the first one" in {
    val executor = getExecutor
    val util = getUtil
    val f0 = util.async(executor, () => 10)
    f0.sync
    val f1 = util.async(executor, () => { delay(); 11 })
    val f = f0.firstSucc(f1)
    f.get should be(10)
  }

, где задержка составляет def delay() = Thread.sleep(4000), а sync синхронизирует будущее (звонки Await.ready(future, Duration.Inf)).Вот как я хочу убедиться, что f0 уже завершена, а f1 завершена ПОСЛЕ f0.Недостаточно, чтобы f0 был завершен, поскольку firstSucc может тасовать фьючерсы.Следовательно, f1 следует отложить до проверки f.get.

Другая идея - создать фьючерсы из обещаний и завершить их в определенный момент времени:

  "firstSucc" should "complete the final future with the first one" in {
    val executor = getExecutor
    val util = getUtil
    val f0 = util.async(executor, () => 10)
    val p = getPromise
    val f1 = p.future
    val f = f0.firstSucc(f1)
    f.get should be(10)
    p.trySuccess(11)
  }

Есть липроще или лучше подходить к определению порядка исполнения?Может быть, другой сервис исполнения, где можно настроить порядок выполнения поставленных задач?Для этого конкретного случая может быть достаточно отложить второе будущее до тех пор, пока не будет проверен результат, но в некоторых случаях ВСЕ фьючерсы должны быть завершены, но в определенном порядке.

Полный код можно найти здесь:https://github.com/tdauth/scala-futures-promises

Контрольный пример является частью этого класса: https://github.com/tdauth/scala-futures-promises/blob/master/src/test/scala/tdauth/futuresandpromises/AbstractFutureTest.scala

Этот вопрос может быть связан с тем, что Scala может использовать Java Executor Services: Управление порядком выполнения задач с ExecutorService

1 Ответ

0 голосов
/ 23 сентября 2018

В большинстве простых случаев я бы сказал, что достаточно однопоточного исполнителя - если вы запускаете свои фьючерсы один за другим, они будут выполняться последовательно и завершаться в том же порядке.

Но похоже, что ваша проблема на самом деле более сложна, чем то, что вы описываете: вы ищете не только способ обеспечить, чтобы одно будущее завершило позже, чем другое, но в целом,чтобы последовательность произвольных событий происходила в определенном порядке.Например, фрагмент вашего вопроса подтверждает, что второе будущее начинается после того, как первое завершает (я не представляю, что означает delay в этом случае, кстати).

Вы можете использовать eventually, чтобы дождаться определенного события, прежде чем продолжить:

   val f = Future(doSomething) 
   eventually { 
      someFlag shouldBe true
   }
   val f1 = Future(doSomethingElse) 
   eventually { 
      f.isCompleted shouldBe true
   }
   someFlag = false   
   eventually { 
      someFlag shouldBe true
   }

   f1.futureValue shoudlBe false
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...