0

我坚持测试可重复的任务。事情在测试之外运行,但在测试中失败。看起来 zio-logging 在测试时的行为有所不同(好像它是“阻塞”的)。当我用普通控制台调用替换日志记录时,它可以工作,当我分叉日志记录调用时也是如此。

谁能给我一个提示我做错了什么或者为什么会这样?

package scheduler

import zio.clock.Clock
import zio.duration.durationInt
import zio.logging.Logging
import zio.test.Assertion.equalTo
import zio.test.environment.TestEnvironment
import zio.test.{DefaultRunnableSpec, ZSpec}
import zio.{Has, Ref, ZIO}

/*
Testing ZIO-based repeated tasks. It works fine locally, but when there is logging within the task it stops working under test.
It looks like it somehow holds execution after first iteration, because adding `fork` to logging statement within `doWorkLogging` makes test pass
*/

object SimpleSpec extends DefaultRunnableSpec {

  private val doWorkLogging = for {
    _   <- ZIO.accessM[Has[Ref[Long]]](_.get.update(_ + 1))
    now <- zio.clock.instant
    _   <- zio.logging.log.info(s"Run $now")
  } yield ()

  private val doWorkConsole = for {
    _   <- ZIO.accessM[Has[Ref[Long]]](_.get.update(_ + 1))
    now <- zio.clock.instant
    _   <- zio.console.putStrLn(s"Run $now")
  } yield ()

  private val logging = Logging.console()

  override def spec: ZSpec[Environment, Any] = suite("simple test")(
    testM("logging + delay work with Clock.live") {
      val counter = Ref.make(0L).toLayer
      val looper  = doWorkLogging *> (zio.UIO.unit.delay(2.seconds) *> doWorkLogging).forever
      (for {
        f     <- looper.fork
        _     <- zio.clock.sleep(5.seconds)
        ref   <- ZIO.service[Ref[Long]]
        count <- ref.get
        _     <- f.interrupt
      } yield zio.test.assert(count)(equalTo(3L))).provideSomeLayer(Clock.live ++ logging ++ counter)
    },
    // Why is this one failing with count = 1?
    testM("logging + delay don't work with TestEnvironment") {
      val counter = Ref.make(0L).toLayer
      val looper  = doWorkLogging *> (zio.UIO.unit.delay(2.seconds) *> doWorkLogging).forever
      (for {
        f     <- looper.fork
        _     <- zio.test.environment.TestClock.adjust(5.seconds)
        ref   <- ZIO.service[Ref[Long]]
        count <- ref.get
        _     <- f.interrupt
      } yield zio.test.assert(count)(equalTo(3L))).provideSomeLayer[TestEnvironment](logging ++ counter)
    },
    // And why this one (with logging replaced with console) works then?
    testM("console + delay work with TestEnvironment") {
      val counter = Ref.make(0L).toLayer
      val looper  = doWorkConsole *> (zio.UIO.unit.delay(2.seconds) *> doWorkConsole).forever
      (for {
        f     <- looper.fork
        _     <- zio.test.environment.TestClock.adjust(5.seconds)
        ref   <- ZIO.service[Ref[Long]]
        count <- ref.get
        _     <- f.interrupt
      } yield zio.test.assert(count)(equalTo(3L))).provideSomeLayer[TestEnvironment](logging ++ counter)
    },
  )
}
4

0 回答 0