Как использовать обычное время в ZIO-Test?

Во время работы над zio-spark мы не можем использовать гоночные эффекты в тестах, которые не используют zio.Clock. Эффекты не прерываются. Есть ли способ это исправить?

      package zio.spark.effect

import zio._
import zio.test.TestAspect.timeout
import zio.test._


object WeirdClocks extends DefaultRunnableSpec {
  def wait(seconds: Int): UIO[Int] = UIO(Thread.sleep(seconds * 1000)).as(seconds)

  override def spec: ZSpec[TestEnvironment, Any] = suite("clock")(
    test("raceTest") {
      wait(5).race(wait(15)) map (n => assertTrue(n == 5))
    } @@ timeout(10.seconds)
  )
}

1 ответ

Это ожидаемое поведение и не имеет ничего общего с тестом ZIO или Clock.

Прерывание в ZIO не возвращается до тех пор, пока эффект не будет успешно прерван, что является важной гарантией сохранности ресурса. В wait(5).race(wait(15)), wait(5)выигрывает гонку через 5 секунд. В таком случае raceпопытки прервать. Однако прерывание обычно происходит «между» эффектами и представляет собой отдельный блок кода побочного эффекта, поэтому в целом нет никакого способа безопасно прервать его. В результате прерывание приостанавливается до тех пор, пока wait(15)завершил выполнение, но к этому моменту прошло 15 секунд, а время теста уже истекло.

Если вы не хотите ждать завершения прерывания, вы можете использовать disconnectоператор, например wait(5).race(wait(15).disconnect). С этим изменением ваш тест пройдет, как написано. Вы также можете использовать attemptBlockingInterruptчтобы направить среду выполнения ZIO на попытку прервать один блок кода с побочными эффектами, подобного этому, путем прерывания основного потока, хотя это относительно тяжеловесно.

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