Как использовать обычное время в 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 на попытку прервать один блок кода с побочными эффектами, подобного этому, путем прерывания основного потока, хотя это относительно тяжеловесно.