Как расширить тестовую среду теста ZIO - PullRequest
0 голосов
/ 03 февраля 2020

Я хочу протестировать следующую функцию:

def curl(host: String, attempt: Int = 200): ZIO[Loggings with Clock, Throwable, Unit]

Если среда просто использует стандартные среды ZIO, такие как Console with Clock, тест будет работать из коробки:

testM("curl on valid URL") {
      (for {
        r <- composer.curl("https://google.com")
      } yield
        assert(r, isUnit))
    }

Среда тестирования будет предоставлена ​​zio-test.

Итак, вопрос в том, как расширить TestEnvironment с помощью моего Loggings модуля?

Ответы [ 2 ]

1 голос
/ 03 февраля 2020

Обратите внимание, что этот ответ для RC17 и значительно изменится в RC18. Вы правы, что, как и в других случаях создания сред, нам нужно реализовать функцию для построения нашей общей среды из имеющихся у нас модулей. Spe c имеет несколько встроенных комбинаторов, таких как provideManaged, чтобы вам не пришлось делать это в самом тесте. Все они имеют «нормальные» варианты, которые будут предоставлять отдельную копию среды для каждого теста в наборе, и «общие» варианты, которые будут создавать одну копию среды для всего набора, когда это ресурс, который стоит дорого создавать. как служба Kafka.

Ниже приведен пример использования provideSomeManaged для предоставления среды, расширяющей тестовую среду до теста.

В RC18 будет множество других предоставляет варианты, эквивалентные тем, что есть в ZIO, а также новую концепцию слоев, которая значительно упрощает создание составных сред для приложений ZIO.

import zio._
import zio.clock._
import zio.test._
import zio.test.environment._

import ExampleSpecUtil._

object ExampleSpec
    extends DefaultRunnableSpec(
      suite("ExampleSpec")(
        testM("My Test") {
          for {
            time <- clock.nanoTime
            _ <- Logging.logLine(
              s"The TestClock says the current time is $time"
            )
          } yield assertCompletes
        }
      ).provideSomeManaged(testClockWithLogging)
    )

object ExampleSpecUtil {

  trait Logging {
    def logging: Logging.Service
  }

  object Logging {

    trait Service {
      def logLine(line: String): UIO[Unit]
    }

    object Live extends Logging {
      val logging: Logging.Service =
        new Logging.Service {
          def logLine(line: String): UIO[Unit] =
            UIO(println(line))
        }
    }

    def logLine(line: String): URIO[Logging, Unit] =
      URIO.accessM(_.logging.logLine(line))
  }

  val testClockWithLogging
      : ZManaged[TestEnvironment, Nothing, TestClock with Logging] =
    ZIO
      .access[TestEnvironment] { testEnvironment =>
        new TestClock with Logging {
          val clock = testEnvironment.clock
          val logging = Logging.Live.logging
          val scheduler = testEnvironment.scheduler
        }
      }
      .toManaged_
}
0 голосов
/ 03 февраля 2020

Вот что я придумал:

testM("curl on valid URL") {
      (for {
        r <- composer.curl("https://google.com")
      } yield
        assert(r, isUnit))
        .provideSome[TestEnvironment](env => new Loggings.ConsoleLogger
           with TestClock {
           override val clock: TestClock.Service[Any] = env.clock
           override val scheduler: TestClock.Service[Any] = env.scheduler
           override val console: TestLogger.Service[Any] = MyLogger()
      })
    }

Использование TestEnvironment с provideSome для настройки моей среды.

...