"Тест использует время, но не опережает время теста" в ZIO Test
После переноса моего теста на RC18 я получаю следующее предупреждение, и тест зависает:
Warning: A test is using time, but is not advancing the test clock, which may result in the test hanging. Use TestClock.adjust to manually advance the time.
У меня есть следующий тест:
val testLayer: ZLayer[Live, Nothing, Loggings with Blocking with Clock] = (Console.live >>> loggings.consoleLogger) ++ Blocking.live ++ TestClock.default
testM("curl on invalid URL") {
for {
fork <- composer.curl("https://bad.xx", 1).flip.fork
_ <- TestClock.adjust(3.second * 2)
r <- fork.join
} yield
assert(r)(isSubtype[DockerComposerException](hasField("msg", _.msg.trim, equalTo("https://bad.xx could not be reached!"))))
}.provideCustomLayer(testLayer)
Я подозреваю, что я создал слои неправильно, так как это единственное изменение, которое я сделал для миграции.
Также не прошел стандартный тест из документации (время было 0):
testM("One can move time very fast") {
for {
startTime <- currentTime(TimeUnit.SECONDS)
_ <- TestClock.adjust(Duration.fromScala(1 minute))
endTime <- currentTime(TimeUnit.SECONDS)
} yield assert(endTime - startTime)(isGreaterThanEqualTo(60L))
}
Когда я определяю такие слои, как:
val testLayer: ZLayer[Live, Nothing, Loggings with Blocking with Clock] = (Console.live >>> loggings.consoleLogger) ++ Blocking.live ++ Clock.live
время вообще не корректируется.
Вот код, который я хочу протестировать:
def curl(host: String, attempt: Int = 200): ZIO[Loggings with Clock, Throwable, Unit] = {
ZIO.effect(
Process(Seq("curl", "--output", "/dev/null", "--silent", "--head", "--fail", host)).!!
).flatMap(r =>
info(s"\n$host is ready to use") *> ZIO.succeed()
).catchAll(t =>
if (attempt == 0)
ZIO.fail(DockerComposerException(s"\n$host could not be reached!", Some(t)))
else
info(s"still waiting ;(") *>
ZIO.sleep(3.second) *>
curl(host, attempt - 1)
)
}
Итак, я хочу перемотать вперед ZIO.sleep(3.seconds)
.
1 ответ
Вам нужно позвонить sleep(duration)
после adjust(duration)
чтобы отразить скорректированное время, когда вы звоните currentTime
. Итак, правильная версия приведенного выше примера:
testM("One can move time very fast") {
for {
startTime <- currentTime(TimeUnit.SECONDS)
_ <- TestClock.adjust(1.minute)
_ <- ZIO.sleep(1.minute)
endTime <- currentTime(TimeUnit.SECONDS)
} yield assert(endTime - startTime)(isGreaterThanEqualTo(60L))
}
Обратите внимание, что это отражено в текущей версии документации здесь, но еще не отражено на веб-сайте, потому что в настоящее время мы публикуем изменения только при выпуске релиза.
Однако я не думаю, что это ваша проблема, поскольку похоже, что ваш эффект просто использует сон.
Я не могу полностью воспроизвести ваш код, но следующий немного упрощенный пример работает правильно:
import zio._
import zio.clock.Clock
import zio.console.Console
import zio.duration._
import zio.test._
import zio.test.environment.TestClock
object ExampleSpec extends DefaultRunnableSpec {
type Logging = Has[Logging.Service]
object Logging {
trait Service {
def logLine(line: String): UIO[Unit]
}
val live: ZLayer[Console, Nothing, Logging] =
ZLayer.fromService { console =>
new Logging.Service {
def logLine(line: String): UIO[Unit] =
console.putStrLn(line)
}
}
def logLine(line: String): ZIO[Logging, Nothing, Unit] =
ZIO.accessM(_.get.logLine(line))
}
def effect(n: Int): ZIO[Clock with Logging, String, Unit] =
if (n == 0) ZIO.fail("fail")
else Logging.logLine("retrying") *> ZIO.sleep(3.seconds) *> effect(n -1)
def spec = suite("ExampleSpec") {
testM("test") {
for {
fiber <- effect(1).flip.fork
_ <- TestClock.adjust(6.seconds)
_ <- fiber.join
} yield assertCompletes
}.provideCustomLayer(Logging.live)
}
}
Может быть, в вашем тесте что-то еще происходит?