Mock verification in Kotlin using MockK and Atrium

I have been working with Kotlin a lot lately. It is a really awesome language. Elegant, powerful and succinct, it fixes most of the annoyances that I had with Java, yet it keeps a certain amount of familiarity that allows the transition from it to be very manageable.

Anyhow, I found myself recently having to build a filter in SpringBoot that I wanted to test. For that I needed to use both a mock and verify that behavior at the same time. Kotlin is evolving quite fast and there are plenty of alternatives to choose from. I will show how to do this with two excellent libraries, MockK, and Atrium.

MockK and Atrium, a powerful combo

MockK seems to be on its way to become the defacto mocking library for Kotlin apps. With a syntax based heavily around lambdas, it just looks like a DSL, as you can see in this example taken directly from their page:

Meanwhile, Atrium is less established, but after getting the recommendation from a colleague, I gave it a try. It uses expect, so for somebody like me who is used to RSpec it is already a win. Anyhow, the syntax takes some time to get used to, but it can be quite expressive. I particularly like combining it with data classes to have exactly one assertion per test instead of many.

The problem at hand

I want to test two things:

  • The filterChain should be called with my wrappedRequest
  • The wrappedRequest should have the correct header in it

Setting up the test

I am using annotations to initialize the mocks (which requires annotating the test with MockKExtension). My filterChain is a RelaxedMockK, which means that its methods will return a default value unless otherwise specified.

A very simple test

Testing the wrapped request

Not so simple anymore! Let’s break it down.

First we are capturing the first argument for doFilter (i.e: the wrapped request). We are creating a new slot by doing slot<ServletRequest>, and capturing it by passing it in the verify block by doing capture(slot). The let block wrapping everything is there so that we don't need an extra local variable (and to feel more kotlin-y inside).

After all this slot.captured contains the wrappedRequest that we created in the filter. Here is where Atrium can shine. We use isA first to check that the request is of the right type. Then inside the block subject is the casted type, where we finally check that our header is there.

Summary

Originally published at https://hceris.com on May 27, 2019.

I develop software for a living. Then I go home and I continue reading about software, because I just cannot get enough. Nowadays I work for ThoughtWorks.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store