简体   繁体   English

如何扩展 ZIO 测试的 TestEnvironment

[英]How to extend the TestEnvironment of a ZIO Test

I want to test the following function:我想测试以下功能:

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

If the environment would just use standard ZIO environments, like Console with Clock , the test would work out of the box:如果环境只使用标准的 ZIO 环境,例如Console with Clock ,则测试将开箱即用:

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

The Test environment would be provided by zio-test .测试环境将由zio-test

So the question is, how to extend the TestEnvironment with my Loggings module?所以问题是,如何使用我的Loggings模块扩展Loggings

This is what I came up:这是我想出来的:

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

Using the TestEnvironment with provideSome to setup my environment.使用TestEnvironmentprovideSome来设置我的环境。

Note that this answer is for RC17 and will change significantly in RC18.请注意,此答案适用于 RC17,并将在 RC18 中发生重大变化。 You're right that as in other cases of composing environments we need to implement a function to build our total environment from the modules we have.你是对的,就像在组合环境的其他情况下一样,我们需要实现一个函数来从我们拥有的模块构建我们的整个环境。 Spec has several combinators built in such as provideManaged to do this so you don't need to do it within your test itself. Spec 内置了多个组合器,例如provideManaged来执行此操作,因此您无需在测试本身中执行此操作。 All of these have "normal" variants that will provide a separate copy of the environment to each test in a suite and "shared" variants that will create one copy of the environment for the entire suite when it is a resource that is expensive to create like a Kafka service.所有这些都有“正常”变体,将为套件中的每个测试提供单独的环境副本和“共享”变体,当它是一种创建成本昂贵的资源时,将为整个套件创建一个环境副本就像 Kafka 服务。

You can see an example below of using provideSomeManaged to provide an environment that extends the test environment to a test.您可以在下面看到使用provideSomeManaged提供将测试环境扩展到测试的环境的示例。

In RC18 there will be a variety of other provide variants equivalent to those on ZIO as well as a new concept of layers to make it much easier to build composed environments for ZIO applications.在 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_
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM