在Zio&#x2B中测试我的API时,集成测试会悬挂。 http4s

发布于 2025-02-06 02:54:26 字数 2686 浏览 2 评论 0原文

我在测试我的第一个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.

如此,测试运行正常,直到服务器启动,然后才能继续执行。

另外,我该如何执行帖子电话而不是接听电话?我在HTTP4S/Zio生态系统中使用HTTP4SCLENTERS,ZHTTP,BLAZECLIENTBUILDERS等人有些迷失。像以前的测试一样,在测试中对我的服务器进行帖子电话的最简单方法是什么?

干杯!

编辑:我检查了服务器在挂在此处时工作正常,我可以从终端进行卷曲调用,并且可以正确响应。因此,很明显,问题是,一旦服务器启动,它就会停留在前面,而不是背景,并且测试没有机会完成执行。

I am having issues testing my first ZIO+HTTP4S application. The test hangs and does not finish.

The code for my App (simplified) is


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

This is my test code. Note that it is basically copypasted from THIS OTHER STACKOVERFLOW QUESTION


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

The problem is that as soon as the server starts, the test stops running and are not executed. The output is

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.

So as you can see, the tests run OK until the server starts and then does not continue the execution.

Also, how could I perform a POST call instead of a GET one? I'm a bit lost in the HTTP4S/ZIO ecosystem with http4sClients, ZHTTP, BlazeClientBuilders and the like. What would be the easiest way of doing a POST call to my server in a test like the previous one?

Cheers!

edit: I’ve checked that the server works fine while hanging in here, I can do CURL calls from a terminal and it responds correctly. So it seems clear that the problem is that as soon as the server is up it stays in the front, not background, and the tests do not have the chance to finish the execution.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

╰◇生如夏花灿烂 2025-02-13 02:54:27

您正在以1秒的速度前进,但您的应用程序可能需要更多时间来运行。同样,您的特定测试将需要无限的时间运行,因为尽管单位测试是Zio瞬时的,但集成测试却不是。

将单位测试的时间提高1秒钟需要0秒。这可能不足以让港口自由。

由于您正在尝试创建集成测试,因此您应该使用真正的时钟,而不是测试套件提供的。

You are advancing the clock by 1 second but your application might require more time to run. Also, your particular test will require infinite time to run because, while unit tests are instantaneous in ZIO, integration tests are not.

Advancing the time of a unit test by 1 second requires theoretically 0 seconds. This might not be enough for the port to become free.

Since you are trying to create an integration test, you should use a real Clock and not the one provided by the test kit.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文