«Тест использует время, но не опережает тестовые часы» в ZIO Test - PullRequest
1 голос
/ 08 апреля 2020

После переноса моего теста на 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 Ответ

1 голос
/ 09 апреля 2020

Вам нужно позвонить 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))
}

Обратите внимание, что это отражено в текущей версии документации здесь , но еще не отражено на веб-сайте, потому что в настоящее время мы только publi sh меняется, когда мы делаем релиз.

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

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

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)
  }
}

Может ли что-то еще происходить в вашем тесте?

...