Как расширить TestEnvironment теста ZIO
Я хочу протестировать следующую функцию:
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 ответа
Обратите внимание, что этот ответ относится к RC17 и значительно изменится в RC18. Вы правы в том, что, как и в других случаях создания сред, нам необходимо реализовать функцию для построения всей нашей среды из имеющихся у нас модулей. В Spec есть несколько встроенных комбинаторов, таких как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_
}
Вот что я придумал:
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
для настройки моей среды.