模拟 BlazeClientBuilder[IO] 以返回模拟客户端 [IO] [英] Mocking of BlazeClientBuilder[IO] to return mock client[IO]

查看:49
本文介绍了模拟 BlazeClientBuilder[IO] 以返回模拟客户端 [IO]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 BlazeClientBuilder[IO].resource 方法来获取 Client[IO].现在,我想模拟客户端进行单元测试,但不知道该怎么做.有没有一种很好的方式来嘲笑这个,我该怎么做?

I am using the BlazeClientBuilder[IO].resource method to get Client[IO]. Now, I want to mock the client for unit testing but cannot figure out how to do so. Is there a good way of mocking this and how would I do that?

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

推荐答案

看来你只需要做类似的事情

It seems you only need to do something like

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

您可以在下面看到一个完整的示例,但我想强调的是,这是一个很好的示例,说明为什么避免模拟您不拥有的 API 是一种很好的做法.

You can see a fully working example below, but I'd like to stress that this is a good example of why it is a good practice to avoid mocking APIs that you don't own.

测试此问题的更好方法是将 http4s 相关代码放在您拥有的类(YourHttpClient 或其他)中,并为该类编写集成测试以检查 http4s 客户端是否执行正确的事情(您可以使用 wiremock 来模拟真正的 http 服务器).

A better way to test this would be to place the http4s related code witin a class you own (YourHttpClient or whatever) and write an integration test for that class that checks that the http4s client does the right thing (you can use wiremock to simulate a real http server).

然后你可以将 YourHttpClient 的模拟传递给依赖它的组件,优势在于你控制它的 API,所以它会更简单,如果 http4s 更新它的 API,你只有一个破坏类,而不必修复数十或数百个模拟交互.

Then you can pass mocks of YourHttpClient to the components that depend on it, with the advantage that you control its API so it will be simpler and if http4s ever updates its API you only have one breaking class rather than having to fix tens or hundreds of mock interactions.

顺便说一句,该示例是使用 mockito-scala 编写的,因为使用 mockito 的 Java 版本会产生更难阅读的代码.

BTW, the example is written using mockito-scala as using the Java version of mockito would have yielded code much harder to read.

    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!!!"

这篇关于模拟 BlazeClientBuilder[IO] 以返回模拟客户端 [IO]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆