代码之家  ›  专栏  ›  技术社区  ›  Kumar Waghmode

模拟BlazeClientBuilder[IO]以返回模拟客户端[IO]

  •  0
  • Kumar Waghmode  · 技术社区  · 7 年前

    我正在使用 BlazeClientBuilder[IO].resource 获取方法 Client[IO]

    class ExternalCall(val resource: Resource[IO, Client[IO]], externalServiceUrl: Uri) {
    def retrieveData: IO[Either[Throwable, String]] = {
    for {
      req <- IO(Request[IO](Method.GET, uri = externalServiceUrl))
      response <- resource.use(client => {
        client.fetch[String](req)(httpResponse => {
          if (!httpResponse.status.isSuccess)
            throw new Exception(httpResponse.status.reason)
          else
            httpResponse.as[String]
        })
      })
    } yield Right(response)
    }
    }
    

    new ExternalCall(BlazeClientBuilder[IO](global).resource).retrieveData
    
    1 回复  |  直到 7 年前
        1
  •  2
  •   ultrasecr.eth    7 年前

    看起来你只需要做一些像

    val resourceMock = mock[Resource[IO, Client[IO]]]
    //stub whatever is necessary
    val call = new ExternalCall(resourceMock).retrieveData
    //do asserts and verifications as needed
    

    编辑:

    更好的测试方法是将与http4s相关的代码放在您自己的类中( YourHttpClient 或者别的什么),并为该类编写一个集成测试,检查http4s客户机是否做了正确的事情(您可以使用wiremock来模拟真正的http服务器)。

    然后你就可以通过模仿 对于依赖它的组件,您可以控制它的API,这样会更简单。如果http4s更新了它的API,那么您就只有一个中断类,而不必修复数十个或数百个模拟交互。

    顺便说一句,这个例子是使用mockito scala编写的,因为使用Java版本的mockito会产生更难阅读的代码。

        val resourceMock = mock[Resource[IO, Client[IO]]]
        val clientMock   = mock[Client[IO]]
        val response: Response[IO] = Response(Status.Ok,
                                              body = Stream("Mocked!!!").through(text.utf8Encode),
                                              headers = Headers(`Content-Type`(MediaType.text.plain, Charset.`UTF-8`)))
    
        clientMock.fetch[String](any[Request[IO]])(*) shouldAnswer { (_: Request[IO], f: Response[IO] => IO[String]) =>
          f(response)
        }
    
        resourceMock.use[String](*)(*) shouldAnswer { (f: Client[IO] => IO[String]) =>
          f(clientMock)
        }
    
        val data = new ExternalCall(resourceMock, Uri.unsafeFromString("http://www.example.com")).retrieveData
    
        data.unsafeRunSync().right.value shouldBe "Mocked!!!"
    
        2
  •  0
  •   slavik    5 年前

    import fs2.Stream
    import org.http4s.Response
    import org.http4s.client.Client
    
    def httpClient(body: String): Client[IO] = Client.apply[IO] { _ =>
        Resource.liftF(IO(Response[IO](body = Stream.emits(body.getBytes("UTF-8")))))
    }
    

    为了将客户机作为资源,您需要用 IO Resource

    Resource.liftF(IO(httpClient("body")))
    
    推荐文章