MockK - nifty mock features I recently discovered
Tags: kotlin, mockk, mocking, testing
Published: 2021-10-19 15:29:24

I am using `MockK` (https://mockk.io/) for a while now in all my Kotlin applications. But just recently I discovered some features I wish I knew beforehand because they really reduce the verbosity of my unit test.

As a developer I am lazy. Therefore I just looked up MockK features I needed at the time without discovering all the other mentioned advanced features. I felt like I will find them when I need them. To be honest - I should have spent some time reading the documentation. Next time I definitely will!

Here is a simple example that improved in readability thanks to some research on MockK features.

## Logic to Test
Here is the logic I wanted to test
```kotlin
    fun dispatchEvent() {
        val taskPayload = Json.encodeToString(TaskPayload("123"))
        val gameEvent: GameEvent = GameEvent(UUID.randomUUID().toString(), "task", DateTime.now(), taskPayload)
        val topic = "projects/barbarus-game/topics/task"
        LOG.info("dispatch event to topic $topic")
        pubSubTemplate.publish(topic, gameEvent).addCallback({ LOG.info(it) }, { LOG.error("failure") })
    }
```

## Unit Test Iteration #0

And here is my initial unit test:

```kotlin
    internal class EventDispatcherTest {
    private val pubSubTemplate: PubSubTemplate = mockk()
    private val eventDispatcher: EventDispatcher = EventDispatcher(pubSubTemplate)

    @Test
    fun `should publish game event message`() {
        val testTopic = "projects/barbarus-game/topics/task"

        every { pubSubTemplate.publish(eq(testTopic), any<GameEvent>()) } returns mockk() {
            every { addCallback(any(), any()) } returns Unit
        }

        eventDispatcher.dispatchEvent()

        verify { pubSubTemplate.publish(eq(testTopic), any<GameEvent>()) }
    }
}
```

I simply want to see if the `dispatchEvent()` function does call the `PubSubTemplate#publish` function as expected.

However `MockK#verify` does not work withou the `pubSubTemplate` mock being defined with a proxy. To satisfy the test runner I added an `every` for `pubSubTemplate` and also had to satisfy the return value (or answer in mockk-domain language). The return value is of type `ListenableFuture`. However I do not need any specific behaviour from it so I just mocked it away.

```kotlin
[...] returns mockk() {
            every { addCallback(any(), any()) } returns Unit
        }

```
This is the part where I mock the `ListenableFuture`.

All of that I had to do, to simply just use `verify` and assert that my `dispatchEvent` function is calling the `PubSubTemplate#$publish` function with the expected `topic` string.

I did a quick google research to see what I can do better.

## Unit Test Iteration #1

The first thing I was wondering about was, if there is a MockK idiomatic way to mock a function that returns `Unit`.

And I found this sweet article/documentation:

https://notwoods.github.io/mockk-guidebook/docs/mockito-migrate/void/

So instead of using `returns Unit` one can simply replace `every` with `justRun`.

The statement now looks a bit slicker

```kotlin
        every { pubSubTemplate.publish(eq(testTopic), any<GameEvent>()) } returns mockk() {
            justRun { addCallback(any(), any()) }
        }
```

But wait! There is more!

### Unit Test Iteration #2

So still I am unhappy with `verify` being dependant on the `every` mock of `pubSubTemplate`. I then stumbled over https://mockk.io/#relaxed-mock

I had no idea what "relaxed" might imply in the context of unit testing. So I took a little research. It says "allows creation with no specific behaviour". So all functions are returning "Simple Values" by default - so me as a developer doesn't need to implement a behaviour with `every` for the called functions of that unit under test.

The only thing I needed to do was to call the `mockk()` function with `relaxed = true` argument.

```kotlin

internal class EventDispatcherTest {
    private val pubSubTemplate: PubSubTemplate = mockk(relaxed = true)
    private val eventDispatcher: EventDispatcher = EventDispatcher(pubSubTemplate)

    @Test
    fun `should publish game event message`() {
        val testTopic = "projects/barbarus-game/topics/task"
        eventDispatcher.dispatchEvent()
        verify { pubSubTemplate.publish(eq(testTopic), any<GameEvent>()) }
    }
}
```

And voila the simple `verify` assertion does it job without the need of a behaviour definition of the mocked class.

## Final Words

I hope I could help one or two developers with this. I'd wish I knew it earlier but hey - better now than never eh?