0

I have one question. I'm using the following function together with the Scala cats Library.

 def process(
      client: Resource[IO, HttpClient] = HttpClientFactory.createClient()
  ): IO[Long] =
    client.use(httpClient => {
      for {
        files <- IO { getFiles() }
        placeMarkers <- IO { sendFile(client) }
      } yield placeMarkers
    })

Now I want to test this code with unit tests and I want to mock the httpClient. I was trying something like this but it does not work:

val resourceIOMock = mock[Resource[IO, HttpClient]]
val httpMock = mock[HttpClient]

doReturn(httpMock).when(resourceIOMock).use(any())

this does not work because of the Mathcers any(). I really don't know how to pass my mock there which then can be configured as needed. From what I see the code never enters the for loop. Can someone help? Thx

Jorge Machado
  • 752
  • 1
  • 8
  • 28

1 Answers1

1

Why you you need to mock Resource? You could pretty much do something like:

// given
val client = mock[HttpClient]
val clientResource = Resource.make[IO, HttpClient](IO.pure(client))(_ => IO.unit)
doReturn(client).when(methodUsedInTest).use(...)

// when
val result = process(clientResource).runSync

// then
assert(...)

If you are building pure values using IO, there is no point in using mocks for them, when you have a pretty good factory methods, especially since IO are data - they don't side effect when you create those values, only when you interpret it (you cannot say that about every random Java class).

So mocking IO, Resource, Ref, makes as little sense as mocking case classes or List/Option/Vector/Set/containers in general. Same if you pass functions as arguments - why mocking if you can just pass implementation? Resource is just a pair of acquire and release functions. You can implement them faster than mockito would mock them.

Mateusz Kubuszok
  • 24,995
  • 4
  • 42
  • 64