Hi! I'm trying to test some `SqsAsyncClient` calls...
# mockk
e
Hi! I'm trying to test some
SqsAsyncClient
calls. Here's an example:
Copy code
class DefaultSqs(
   client: SqsAsyncClient,
   queueUrl: String
) {
   suspend fun purge() {
      sqsClient.purge {
         it.queueUrl("queue-url")
      }.await()
   }
}
The signature of this
sqsClient.purge
method I'm calling is:
Copy code
CompletableFuture<PurgeQueueResponse> purgeQueue(Consumer<PurgeQueueRequest.Builder> purgeQueueRequest)
my unit test is something like:
Copy code
@Test
    fun `test purge`() {
        val mockClient = mockk<SqsAsyncClient> {
            coEvery {
                purgeQueue(any<Consumer<PurgeQueueRequest.Builder>>())
            } returns CompletableFuture.completedFuture(mockk())
        }
        val sqs = DefaultSqs(mockClient, "queue-url")

        runBlocking { sqs.purge() }

        coVerify(exactly = 1) {
            // how to verify here??
        }
    }
and I'd like to verify that the consumer was calling the queue-url setter with the right value. Is there a way to do it?
Answering my own question maybe it helps for others. In my case (and probably this is the usual case), such a method which is DSL-like, it calls some real builders in the background and ideally there is another method which does the real work and takes the built object as an input. Like, in my case, `SqsAsyncClient`:
Copy code
// the method I call from my code

default CompletableFuture<PurgeQueueResponse> purgeQueue(Consumer<PurgeQueueRequest.Builder> purgeQueueRequest) {
        return purgeQueue(PurgeQueueRequest.builder().applyMutation(purgeQueueRequest).build());
    }

// the method being called from there ^^
default CompletableFuture<PurgeQueueResponse> purgeQueue(PurgeQueueRequest purgeQueueRequest)
So the trick is to use
spyk
instead of
mockk
so unmocked methods would just execute their implementation, and mock out the inner method like this:
Copy code
@Test
    fun `test purge`() {
        val slot = slot<PurgeQueueRequest>()
        val mockClient = spyk<SqsAsyncClient> {
            coEvery { purgeQueue(capture(slot)) } returns CompletableFuture.completedFuture(mockk())
        }

        val sqs = DefaultSqs(mockClient, "region", "queue-url")

        runBlocking { sqs.purge() }

        coVerify(exactly = 1) {
            mockClient.purgeQueue(any<Consumer<PurgeQueueRequest.Builder>>())
        }

        assertEquals("queue-url", slot.captured.queueUrl())
    }
Update figured out a simpler way by just simply mocking out the builder method with
callOriginal
and mock the inner method:
Copy code
@Test
    fun `test purge`() {
        val slot = slot<PurgeQueueRequest>()
        val mockClient = mockk<SqsAsyncClient> {
            coEvery { purgeQueue(any<Consumer<PurgeQueueRequest.Builder>>()) } answers { callOriginal() }
            coEvery { purgeQueue(capture(slot)) } returns CompletableFuture.completedFuture(mockk())
        }

        val sqs = DefaultSqs(mockClient, "region", "queue-url")

        runBlocking { sqs.purge() }

        coVerify(exactly = 1) {
            mockClient.purgeQueue(match<PurgeQueueRequest> { it.queueUrl() == "queue-url" })
        }
    }