我在测试我的第一个 ZIO+HTTP4S 应用程序时遇到问题。测试挂起且未完成。
我的应用程序(简体)的代码是
object Main extends App {
def server: ZIO[AppEnvironment, Throwable, Unit] =
for {
(...)
fullApp <- ZIO.runtime[AppEnvironment].flatMap { implicit rts =>
BlazeServerBuilder[AppTask](ec)
.bindHttp(api.port, api.endpoint)
.withHttpApp(CORS(httpApp))
.serve
.compile[AppTask, AppTask, CatsExitCode]
.drain
}
} yield fullApp
override def run(args: List[String]): ZIO[ZEnv, Nothing, ExitCode] = {
server.provideSomeLayer[ZEnv](appEnvironment).tapError(err => putStrLn(s"Execution failed with: $err")).exitCode
}
}
这是我的测试代码。请注意,它基本上是从另一个堆栈溢出问题复制粘贴的
object ApiTest extends DefaultRunnableSpec {
val ec: ExecutionContext = ExecutionContext.global
def httpServer = Main.run(List()).forkManaged.toLayer
val clockDuration = ofSeconds(1)
val blocker = Blocker.liftExecutionContext(ec)
//did the httpserver start listening on 8080?
private def isLocalPortInUse(port: Int): ZIO[Clock, Throwable, Unit] = {
IO.effect {
println("checking for local port in use")
new Socket("0.0.0.0", port).close()
}
.retry(Schedule.linear(clockDuration) && Schedule.recurs(10))
}
override def spec: ZSpec[Environment, Failure] =
suite("MainTest")(
testM("Health check") {
for {
_ <- TestClock.adjust(clockDuration).fork
_ = println("1")
_ <- isLocalPortInUse(8080)
_ = println("2")
client <- Task(JavaNetClientBuilder[Task](blocker).create)
_ = println("3")
response <- client.expect[String]("http://localhost:8080/healthcheck")
_ = println("4")
} yield assert(response)(equalTo(""))
}
).provideCustomLayerShared(httpServer)
}
问题是,一旦服务器启动,测试就会停止运行并且不执行。输出为
1
checking for local port in use
checking for local port in use
<server init message>
In Suite "MainTest", test "Health check" has taken more than 1 m to execute. If this is not expected, consider using TestAspect.timeout to timeout runaway tests for faster diagnostics.
如您所见,测试运行正常,直到服务器启动,然后不继续执行。
另外,我如何执行 POST 调用而不是 GET 调用?我在HTTP4S/ZIO生态系统中有点迷失,包括http4sClients,ZHTTP,BlazeClientBuilders等。在像上一次测试这样的测试中对我的服务器进行 POST 调用的最简单方法是什么?
干杯!
编辑:我已经检查了服务器在这里挂起时是否正常工作,我可以从终端进行 CURL 调用并且它响应正确。因此,很明显,问题在于一旦服务器启动,它就会停留在前面,而不是后台,并且测试没有机会完成执行。
您将时钟提前 1 秒,但您的应用程序可能需要更多时间才能运行。此外,您的特定测试将需要无限的时间来运行,因为虽然单元测试在 ZIO 中是即时的,但集成测试不是。
将单元测试的时间提前 1 秒理论上需要 0 秒。这可能不足以使端口变为空闲。
由于您正在尝试创建集成测试,因此应使用实际Clock
,而不是测试工具包提供的。